Está en la página 1de 103

sisOpe Temario Curso: 22/23

Horas

1 INTRODUCCIÓN

5…

2 PROCESOS Y THREADS

3 GESTIÓN DE MEMORIA

Gestión de Procesos 4 ENTRADA / SALIDA 1


sisOpe 2. Procesos y Threads Curso: 21/22
• Introducción
• Procesos
• Visión abstracta
• Esbozo de implementación
• Threads (Procesos ligeros)
• Comunicación entre procesos
• Condición de carrera
• Exclusión mutua y región crítica
• Implementación de la exclusión mutua
• Paso de mensajes
• Planificación de procesos
• Criterios
• Políticas
• Sistemas multiprocesador
Gestión de Procesos 2
INTRODUCCIÓN
Interesa tener máquinas que ejecuten varios procesos al mismo tiempo

T3 Aprovechar tiempos muertos E/S


Soluciones elegantes concurrentes
T2
Más rapidez con más de una CPU
T1 pseudoparalelismo
t
18
T3 CPU2
Con multiprocesadores
T2 también interesa multiplexar
CPU1 las CPU’s
T1
t
Gestión de Procesos 13 3
PROCESOS (Visión abstracta: Recordar sus llamadas)
Dos relaciones típicas entre proceso Padre y proceso Hijo:

1. Procesos independientes: La “shell” crea un proceso para ejecutar


un programa de usuario “ls”
¿fork + exec?
a. Debe cargarse el ejecutable P
shell
en memoria
H ls
b. Dotarle de registros, pila, etc. ls.exe

2. Procesos cooperantes: Un servidor Web crea un proceso para


atender una petición de un cliente ¿fork?
P
a. El código ya está en memoria
H web Parecido a
b. Dotarle de registros, pila, etc. Threads

Gestión de Procesos 4
PROCESOS (Visión abstracta: Recordar sus llamadas)
Proceso de arranque y grupos de procesos /etc/inittab
P1 id:rlevel:action:process

P2 P3 P5 /etc/rc5.d

P4 P7 login as:
?
init
Password: gdm
PC1> login
login /etc/rc.d/rc 5
P6 rlevel
0 Halt
1 Monousuario /etc/passwd
bash xinetd
2 MultiSinRed pcarazo:........:/bin/bash
Red
3 MultiConRed
5 X11
6 Reboot
grupo de procesos
? putty
Gestión de Procesos 5
PROCESOS (Visión abstracta: Recordar sus llamadas)

Gestión de Procesos 6
Esbozo de implementación
¿Cómo es el ciclo de vida de un proceso?
CPU
Creación
P3
P4
P1
P3 P2
P4
P3
P1
P2
P3 P3
P4
P1
P1
P2
P3 ? Terminación

Expulsión ¿P1.read(disco,
¿P2.sleep(5
¿P1
¿P4
¿P3 mucha
fin
read(cinta,
termina?
E/S?CPU?
)? ))?

P1 ¿Estados de un proceso?
• EnEjecución
Activo
• Preparado
P2 • EnEspera o Bloqueado

Ejecu.
P4
Prep. Espera
Gestión de Procesos 7
Diagrama de transición de estados de un Proceso
F.R.
¿exec?
forkp wait
¿forkh? ¿kill?
exit ¿forkp?
F.R. EnEjecución
sleep wait
wait
exit ¿forkp? sleep

forkh F.R.
Preparado ¿forkp? EnEspera

exit F.R.

Gestión de Procesos 8
Esbozo de implementación en términos más informáticos
El contexto de un proceso está distribuido en varias zonas
• Contexto de memoria (Código y Datos)
• MP/MSec
Bloque de control (descriptor) del Proceso MP
(S.O.)
• Contexto del procesador
Reg/MP/MSec
MP
Ejecutándose MSec
CPU

i la
p
S.O.
Bloqueado
Gestión de Procesos 9
Esbozo de implementación ( ¿Cuántos procesos? )

142

¿#Procesos ilimitado o un máximo predeterminado?

MINIX-2 32
MINIX-3 100 + 4

Linux V2.4 … ¿? Linux .. V2.2 NR_TASKS [512]

Gestión de Procesos 10
Esbozo de implementación ( ¿Cuántos procesos? )
¿#Procesos ilimitado o un máximo predeterminado?
maxProcesos: constant:=100; Reservado

type idProceso is NATURAL range 0..maxProcesos;


type descriptorProceso is p_nr
record 584
pid: ----------; 0  Descriptor
--------------- libre ¿Correcto?
end record;
procesos : array[1..maxProcesos] of descriptorProceso;
ejecutandose : idProceso;
¿ fork ?
1 2 3 4 50 97 98 99 100

proc

Gestión de Procesos 11
Esbozo de implementación ( ¿Cómo dar los PID’s? )
type descriptorProceso is ¿Problemas?
record
pid: idProceso; • 99 procesos en el sistema
0..100
--------------- • Hago ps y veo un proceso
end record; mío (50)
• Me dispongo a kill –9 50
Mejor espaciar más los códigos
• Mi proceso termina antes
pid: NATURAL; 0..65535... del kill y se crea otro
ejecutandose proceso con el código 50
Algo más complejo ¿ 584 o 50 ? ¡ Mato a otro proceso !
dar PID’s
fork exit
1 2 3 4 50 97 98 99 100
584

Gestión de Procesos ¿ kill ? 12


Esbozo de implementación ( ¿Cuántos procesos? )
¿#Procesos ilimitado o un máximo predeterminado?
maxProcesos: constant:=100;
type idProceso is NATURAL range 0..maxProcesos;
type descriptorProceso is
record
P
50 PidInterno
pid: NATURAL;
584 PidExterno getpid
---------------
end record;
procesos : array[1..maxProcesos] of descriptorProceso;
ejecutandose : idProceso;
1 2 3 4 50 97 98 99 100
584 proc

Gestión de Procesos 13
Esbozo de implementación ( ¿Estados y su gestión? )
type unEstado is (ejecutandose, preparado,
espLapso, espFinHijo, zombie);

Gestión de Procesos 14
Esbozo de implementación ( ¿Estados y su gestión? )

fork2Bis

Gestión de Procesos 15
Esbozo de implementación ( ¿Estados y su gestión? )
type unEstado is (ejecutandose, preparado,
espLapso, espFinHijo, zombie);
type descriptorProceso is CPU queda libre. ¿A qué Pi se la doy?
record
pid: NATURAL; • Recorro procesos buscando uno que
estado: unEstado; esté preparado Lento e injusto
sig: IdProceso; • Si decido elegir al Pi que lleva más
end record; tiempo preparado, lo mejor cola FIFO
type unaCola is record
primero: idProceso := 0; preparados: unaCola;
ultimo: idProceso:= 0; ejecutandose: idProceso;
end record;
1 2 3 4 50 97 98 99 100

Gestión de Procesos 16
Esbozo de implementación ( ¿Estados y su gestión? )
• Recorro procesos buscando uno que esté preparado Lento e injusto

P97 P57 P4

1057 1058 1059 ti


09:25:30 09:25:31 CPU al P4?

• ¿Marca de tiempo?
• time ¿ Algo mejor que antes ? ¿INANICIÓN?

• antigüedad contPasoAPreparados
1056 ¿Desborda?
Lento ++
0
Gestión de Procesos 17
Esbozo de implementación ( ¿Procesos bloqueados? )
espLapso => Muy parecido a preparados, sólo que es necesario indicar
cuándo despertarles o cuánto falta para despertarles, ...
¿ gcc –O3 ?
--
sleepHasta (DDMMAA hhmmss) sleepDurante (segundos)

38 bits => 5 | 7 bytes 24 bits => 3 bytes

localtime
time
?
segundos ? DDMMAA
hhmmss

mktime
Gestión de Procesos 18
Esbozo de implementación ( ¿Procesos bloqueados? )
espLapso => Muy parecido a preparados, sólo que es necesario indicar
cuándo despertarles o cuánto falta para despertarles, ...
type descriptorProceso is • El campo sig me sigue sirviendo
record para encadenar
pid: NATURAL; 80
estado: unEstado; • ¿Mejorable? P80.sleep(8)
83
sig: idProceso; P33.sleep(10)
lapso: NATURAL; 4 97 50
end record;
5 52 15
espLapso : unaCola;

1 2 3 4 50 97 98 99 100

5 25 10

Gestión de Procesos 19
Esbozo de implementación ( ¿Procesos bloqueados? )
espFinHijo => El fin de un hijo sólo puede estar esperándolo su Padre.
Puede no ser necesaria una cola.
24 50
P 1000 ¿Quién H 1040 • Buscar al H1040  h50
antes? • No existe
-------------
-------------
waitpid(1040)
-------------
-------------
-------------
• No es hijo mío ?
• Mi hijo está Zombie
------------- exit(33) • Mi hijo está vivo
------------- -------------
// Localizar H en procesos 
h
24 50 if (h.estado != zombie) // vivo
1000 1040 p.estado = espFinHijo;
24 p.sig := h;
liberarCPU y dársela a otro Pi
padre  24 | 1000 else // Hijo ya hizo exit
Gestión de Procesos 20
Esbozo de implementación ( ¿Procesos bloqueados? )
espFinHijo => El fin de un hijo sólo puede estar esperándolo su Padre.
Puede no ser necesaria una cola.
24 50
P 1000 ¿Quién H 1040 // Localizar H en procesos 
antes? h
------------- ------------- if (h.estado != zombie) // vivo
------------- ------------- p.estado = espFinHijo;
waitpid(1040)
-------------
-------------
?
-------------
exit(33)
-------------
p.sig := h;
liberarCPU y dársela a otro Pi
else // Hijo ya hizo exit
p = procesos[enEje].padre;
if ((p.estado = espFinHijo)
24 50 && (p.sig = h) ) // enEje
1000 1040 Transferir estado terminación
24
liberar recursos y descriptor
desbloquear Padre y darCPU
else // Padre no está waitpid
Gestión de Procesos 21
Esbozo de implementación ( ¿Procesos bloqueados? )
espFinHijo => El fin de un hijo sólo puede estar esperándolo su Padre.
Puede no ser necesaria una cola.
type descriptorProceso is • El Padre (P) hace wait (H):
record
-- Localizar H en procesos => h
pid: NATURAL;
if h.estado = zombie then
padre: idProceso;
Liberar descriptor del Hijo y
estado: unEstado;
continuar al Padre
sig: idProceso;
else -- hijo vivo
lapso: NATURAL;
p.estado:=espFinHijo; p.sig:=h;
end record;
liberar CPU;
• Un Hijo(H) termina exit:
If (p.estado = espFinHijo) & (p.sig = h) then
liberar recursos y descriptor Hijo y continuar Padre
else
h.estado := zombie; liberar recursos h y liberar CPU
Gestión de Procesos 22
Esbozo de implementación ( Concluyendo )
maxProcesos : constant := 100;
type idProceso is NATURAL range 0..maxProcesos;
type unEstado is (ejecutandose, preparado,
espLapso, espFinHijo, zombie);
type descriptorProceso is ¿ fork y exec ?
record
pid: NATURAL; type unaCola is
padre: idProceso; record
estado: unEstado; primero: idProceso := 0;
sig: idProceso; ultimo: idProceso := 0;
lapso: NATURAL; end record;
SP: address;
procesos : array [1..maxProcesos] of
memoria: ----------;
descriptorProceso;
ficheros: ----------;
ejecutandose: idProceso;
tiempos: ----------;
preparados, espLapso: unaCola;
end record;
Gestión de Procesos 23
Esbozo de implementación ( Concluyendo )
• fork y exec
forkh pid = 0
---------- • Buscar descriptor libre
fork () • Buscar memoria libre
---------- • Copiar y …
exec( … ) • Buscar PID y …
---------- • Meter en preparados
fork () • Asignar CPU
----------
exec( … )
---------- ¿ exec ?
----------

----------
?
----------

----------
Gestión de Procesos 24
Esbozo de implementación ( Otro ejemplo )

Campos en una entrada a la tabla de procesos

Gestión de Procesos 25
Esbozo de implementación ( El Cambio de Contexto )
• Llamada al Sistema
• Fin de Proceso Trap
Causas? Bien/Mal Mecanismo similar

• Interrupción (E/S, F.R.) ¿Cuántos?


Supongamos como causa “Fin de Rodaja”
¿No hay
Hw Ens. C/Modula/Ada Ens. procesos
preparados?
ejecu-
tándose Pi S.O. Pj
Planificador
(1) (2) (3) (4)
(1) Reconocimiento de la interrupción (3) 1 Recorrer dormitorio
2 Elegir siguiente proceso
(2) Salvar reg (Pi) y conmutar de pila
(4) Recuperar reg (Pj) y cederle control

Gestión de Procesos
Dispatcher 26
Esbozo de implementación ( El Cambio de Contexto )
Vector de
---------- Interrupciones
DIV 0 S.O.
divu d5,d0
---------- -------
-------
-------
-------
------- -------
INT 3 -------
-------
---------- -------
------- -------
---------- ------- -------
------- -------
sleep(10) TRAP #0 ------- -------
------- -------
---------- ------- -------
------- -------
---------- ------- -------
exit(0) -------
------- Cambio de
-------
------- contexto
-------
Se salva el SR y PC
Gestión de Procesos 27
Esbozo de implementación ( El Cambio de Contexto )
• Recuperar registros (Pj) y cederle control
SO SO SO

Pi CPU Pi CPU Pi CPU

Pj Pj Pj
rte

Gestión de Procesos 28
Esbozo de implementación ( El Cambio de Contexto )
vmstat

Gestión de Procesos 29
Threads ( Visión abstracta )
Modelo de procesos más común  Espacios de direcciones disjuntos
Pi Pj

Registros fork Registros exec


Código Código
ls.exe
Datos, Pila Datos, Pila
Ficheros Ficheros

Facilita protección PiPj, pero: ¿Y si los procesos son cooperantes?


• Creación laboriosa • Objetivo común
• Cambio de contexto pesado Colaboración vs agresión
(procesador + entorno) Protección más laxa
TLB’s, cachés, ... • Pueden desear mantener
• Comunicación vía mensajes datos comunes con los
más seguro pero más lento menores costes de tiempo
Gestión de Procesos 30
Threads ( Visión abstracta )
Procesos Ligeros  Espacios de direcciones no disjuntos
Ti Tj Servidor de localización
Registros Registros de utilidades
Pila Pila
C1 consulta
Código, Datos C2 alta
Ficheros
ons ul t a S
Cn c
¡ Muy eficaz con multiprocesadores !
petición
• Soportados de dos formas:
• En el espacio del S.O. respuesta
• En el espacio del Usuario
Biblioteca BD utilidades
Gestión de Procesos 31
Threads ( “Linux” )
int __clone (int (*fn) (void *arg), void *child_stack, int flags, void *arg)
Como fork sólo que crea un Thread “Específico de Linux”
Thread soportado como tal por el S.O. (no portable)

Biblioteca pthread (API POSIX 1003.1c)

int pthread_create (pthread_t * thread, atributos, funcion,


argumentos)
pthread_t pthread_self (void)
int pthread_exit (void *estado)
int pthread_join (pthread_t thread, void **estado)
................................................... ¿ fork + threads ?
...................................................
Gestión de Procesos 32
Threads ( Ejemplos de uso: tonto.c )
#include <pthread.h>
#include <stdio.h>
int main (int argc, char *argv[]){
pthread_t tA, tB;
int datoA=0; datoB=0; datoC=0; ?
void *A (void *basura) { void *B (void *basura) {
datoA = 1000; int datoC; datoB = 2000; int datoC;
sleep (5); sleep (5);
printf (“datoB=%d\n”, datoB); printf (“datoA=%d\n”, datoA);
pthread_exit (NULL); pthread_exit (NULL);
} }

pthread_create(&tA, NULL, A, NULL);


pthread_create(&tB, NULL, B, NULL);
A B
pthread_join (tA, NULL);
pthread_join (tB, NULL);
0
1000 0
2000
exit (0); datoA datoB
}
Gestión de Procesos 33
Threads ( Ejemplos de uso: descifrar )
Padre esesi

Hijo
SIGUSR1

¿ Con memoria común y threads ?

Gestión de Procesos 34
Threads ( Ejemplos de uso: despara2Threads.c )

int encontrada=0;
char laPasswordCifrada[LONG_CLAVE_CIFRADA+1];

void *esclavo (void *parametro) { ..... }

int main(int argc, char **argv) {


int i;
pthread_t pids[2];

strcpy (laPasswordCifrada, argv[1]);


for (i=0; i<2; i++)
pthread_create (&pids[i], NULL, esclavo, (void *) i);
for (i=0; i<2; i++)
pthread_join (pids[i], NULL);
return 0;
}

35
Gestión de Procesos
Threads ( Ejemplos de uso: despara2Threads.c )

void *esclavo (void *parametro) {


int yo;
char laPasswordCruda [LONG_CLAVE_CRUDA +1];

yo = (int) parametro;
if (yo == 0) strcpy (laPasswordCruda, "aaaaa\0");
else strcpy (laPasswordCruda, "naaaa\0");
buscar(yo, laPasswordCifrada, laPasswordCruda);
printf ("Termina esclavo %d\n",yo);
pthread_exit (NULL);
}

Gestión de Procesos 36
Threads ( Ejemplos de uso: despara2Threads.c )

void buscar(int yo, char *cifrada, char *laPassword) {


int i;
struct crypt_data datosCrypt;

datosCrypt.initialized = 0;
for (i=0; i<(NUM_COMBINACIONES/2); i++) {
if ((i%456976) == 0) printf("%s\n", laPassword);
if (strcmp(cifrada, crypt_r(laPassword, "aa",
&datosCrypt)) == 0) {
printf ("%d la password es: %s\n", yo, laPassword);
encontrada = 1;
break;
}
if (encontrada) break;
siguientePassword(laPassword);
}
}

Gestión de Procesos 37
Threads ( Ejemplos de uso: `despara2Threads.c )
E0 esesi ojosi

E1

Clave Secuencial Paralelo


esesi 8,740 8,960
ojosi 31,352 2,596

2 Xeon E5520 Quad


2,26GHz • 8ML3 • 12GB • 500GB

Gestión de Procesos 38
Threads ( En el espacio de usuario )

• El S.O. no los soporta


• Cambio contexto rápido
• Distintos planificadores

• read, … ¡ Bloqueantes !
• Falta de página
• ¡Planificación expulsora!

pthread_create pthread_join

Gestión de Procesos
pthread_exit pthread_self 39
Threads ( En el espacio del S.O. )

Gestión de Procesos 40
Comunicación entre Procesos
Los procesos cooperantes necesitan mecanismos para sincronizarse y
comunicarse información de forma segura
Sincronización  Ordenación temporal de la ejecución de
procesos
Canal de Panamá A antes queTortilla
B de patatas
Batir Pelar Pelar
Huevos Cebollas Patatas

Mezclar, Añadir Sal y Freir


Comunicación  Paso de información entre tareas
Síncrona o Asíncrona
Filtros Unix:
who | wc | sed -e ‘s/ [ ]*/:/g’ | cut -d: -f2
Gestión de Procesos 41
Condiciones de Carrera
La falta de sincronismo entre procesos cooperantes da problemas
• Canal de Panamá  Barco encallado
• Tortilla de Patatas  No hay quien se la coma
• Uso de datos / recursos comunes  Inconsistencia

¡Que buen ¡Me


negocio! tangan!

Gestión de Procesos 42
Condiciones de Carrera (Modelización con threads)
int cuenta;
void *taxista(void *parametro) { ..... }
int main( int argc, char *argv[] ) {
int i, numEsclavos;
pthread_t pids[MAX_ESCLAVOS];

numEsclavos = atoi(argv[1]);
cuenta = 0;
// Crear esclavos y esperar a que terminen su trabajo
for (i=0; i<numEsclavos; i++)
pthread_create (&pids[i], NULL, taxista, (void *) i);
for (i=0; i<numEsclavos; i++)
pthread_join (pids[i], NULL);
printf ("Total recaudacion = %d\n", cuenta);
return (0);
}
Ingreso de Taxista 1 = 80729
Ingreso de Taxista 2 = 80618 + 161347
Total recaudacion = 161096
Gestión de Procesos 43
Condiciones de Carrera (Modelización con threads)
void *taxista (void *parametro) {
// Variables
recaudacion = 0; mio = 0; Hacer
do { Carrera
espera = random() % MAX_ESPERA;Buscar
for (i=1; i<espera; i++); Cliente
importe = random (maxImporte);
mio = mio + (importe / RATIO_TAXISTA);
cuenta = cuenta + importe –
(importe / RATIO_TAXISTA);
recaudacion = recaudacion + importe;
} while (mio < SUELDO_DIA);
printf (“Ingreso de Taxista %d = %d\n”,
yo, recaudacion – mio); Ingreso
pthread_exit (NULL);
}Gestión de Procesos 44
Condiciones de Carrera (Modelización con threads)

?
Fallos x 1.000
Threads pc1:4Cores pc9:8Cores
2 7 207
4 64 926
8 230 1.000
16 533 1.000
32 830 1.000

Gestión de Procesos 45
Condiciones de Carrera (El problema)
3: cuenta := cuenta + importe

3.1: PUSH importe T1.importe T2.importe


10.000 1.500
3.2: PUSH cuenta
T1.SP T2.SP
3.3: ADDP
3.4: POP cuenta 3.3 3.3
5.000 5.000
¿problema? 15.000
10.000 6.500
1.500

T2 3.1, 3.2 3.3, 3.4

T1 3.1, 3.2 3.3, 3.4

cuenta cuenta cuenta


5.000 15.000 6.500
Gestión de Procesos 46
Exclusión mutua y Región crítica (La solución)
Integridad
Datos
Comunes
RC

Aquí cero, Aquí como


uno o más Pi máximo un Pi

RC Exclusión
Mutua

Los Pi indicarán cuándo EntranEnRC y cuándo SalenDeRC


Gestión de Procesos 47
Exclusión mutua y Región crítica (La solución)
EntrarEnRC;
cuenta := cuenta + importe –
(importe div ratioTaxista);
SalirDeRC;

REQUISITOS
• En una misma Región Crítica no más de un proceso

• Sin supuestos: #µP, #Pi, velocidades relativas, .....

• Ningún Pi fuera de su Región Crítica bloqueará a otros Pj

• Decisión de quién entra a una Región Crítica en un tiempo finito

Gestión de Procesos 48
Implementación de la Exclusión Mutua
Mecanismos: Hw Sw
• Inhibición de interrupciones • Semáforos S.O.
• Cerrojos (espera activa) • Monitores Lenguaje
Inhibición de interrupciones

Taxistas DirecciónGeneralDeTráfico
InhibirInterrupciones repeat
cuenta := cuenta + importe aguardarAgazapados y ¡foto!
PermitirInterrupciones InhibirInterrupciones
numeroMultas++
 RC muy corta o pueden PermitirInterrupciones
perderse interrupciones until cubiertoCupo
 Exclusión total vs parcial
 Sólo válido en monoprocesador  Peligroso en manos del usuario
Gestión de Procesos  Útil dentro del propio S.O. 49
Implementación de la Exclusión Mutua ( Cerrojos )
Una variable “cerrojo” por cada RC distinta que indica Libre/Ocupada

Taxistas Guardia Civil


Entrar (RCTaxistas) Entrar (RCDGT)
cuenta := cuenta + importe numeroMultas++
Salir (RCTaxistas) Salir (RCDGT)
entrar tst.b RCT
while RCT = ocupada do null; bnz entrar
RCT := ocupada move.b
#$FF,RCT
cuenta := cuenta + importe;
push
RCT := libre importe
push cuenta
addp
¡ No funciona ! pop cuenta
Gestión de Procesos salir move.b 50
Implementación de la Exclusión Mutua ( El cerrojo falla )
RCT RCT RCT
00 FF FF

T2

T1

---------------- ---------------- bnz entrar


---------------- ---------------- move.b #$FF,RCT
entrar tst.b tst.b RCT ----------------
bnz entrar ----------------
RCT move.b #$FF,RCT ----------------
T1.SR ----------------
----------------
Z ----------------
1 T2 dentro RCT ¡¡ T1 también dentro RCT !!
Gestión de Procesos 51
Implementación de la Exclusión Mutua ( Un cerrojo seguro? )
Algoritmos: Dekker, Dijkstra, Knuth, Peterson, .......
El Hw ayuda con una instrucción atómica que consulta y cambia valor
tst.b cerrojo
tas.b cerrojo, valor
move.b valor,cerrojo

entrar tas.b
F.R. ¿Habrá problemas?
RCT,#$FF
bnz ¡SI!
entrar No funciona en multiprocesador
push ya que TAS es ininterrumpible
importe dentro de un procesador, pero
push supone dos accesos al bus:
cuenta 1 Lectura del cerrojo
addp
Gestión de pop
Procesos
2 Modificación del 52
Implementación de la Exclusión Mutua ( Un cerrojo seguro! )
RCT RCT RCT RCT
00 FF FF FF

T2

T1

---------------- ----------------
bnz entrar tas.b RCT,#$FF
---------------- ----------------
------------- bnz entrar
tas.b RCT,#$FF tas.b RCT,#$FF
-------------
bnz entrar
-------------
T1.SR ------------- T2 no puede
Z T1 en RCT entrar en RC
mientras está T1
1
Gestión de Procesos 53
Implementación de la Exclusión Mutua ( TAS todavía falla! )
P1 P2
TAS  PedirBus, Leer, PedirBus, Escribir
P1  T1 PB, L1, PB, E1
RCT ???
P2  T2 PB, L2, PB, E2

tas.b RCT,#$FF L1, E1, L2, E2 L2, E2, L1, E1 L1, L2, E1, E2
bnz entrar
T1 T2 T2 T1 T1 T2

( El Hw nos ayuda )

TASL “TAS with Lock”  BusLock, Leer, Escribir, BusRelease


tasl.b RCT,#$FF ¡ Todavía dos problemas !
bnz entrar PH
• Espera Activa
--------------------- PL • Inversión de prioridades
---------------------
Gestión de Procesos
deadLock ¿ Qué hacer ? 54
Implementación de la Exclusión Mutua ( RC POSIX )

int pthread_mutex_lock (pthread_mutex_t *regionCritica)


int pthread_mutex_unlock (pthread_mutex_t *regionCritica)

¿Posible implementación (sin espera activa)? Multiprocesador

type pthread_mutext_t is lock (RCT): ?


record ¡ Ojo ! inhibir interrupciones tasl
libre : BOOLEAN; salvarEstado(ejecutandose)
cola : unaCola; if RCT.libre
end record; then RCT.libre = FALSE
RCT Pi Pj else meter (ejecutandose,
F RCT);
ejecutandose =
planificar();
Gestión de Procesos 55
recuperarEstado(ejecutandose)
Implementación de la Exclusión Mutua ( RC POSIX )
• Se tiene que saber si Libre u Ocupada y además:

pthread_mutex_init T3.lock

T1.lock T2.lock
T3 T2

T1 T1

Libre Ocupada Ocupada

Ti.unlock Ti.unlock T1.unlock


• Bastaría con un estado y una cola de espera para entrar
Gestión de Procesos 56
Implementación de la Exclusión Mutua ( Semáforos )
Soportado por el S.O. garantiza exclusión mutua sin espera activa
type Semaforos is private;
Inicializar (S: Semaforos; Valor: NATURAL);
Operaciones
Bajar (S); -- Puede bloquear al proceso (Si Valor = 0)
Atómicas
Subir (S); -- Puede desbloquear a UN proceso

Dar soporte a RC con semáforos es fácil:


Inicializar (S_RCT, 1) Inicializar (S_RCGC, 1)
--------------- ---------------
Bajar (S_RCT) Bajar (S_RCGC)
Cuenta := Cuenta + Importe numeroMultas++
Subir (S_RCT) Subir (S_RCGC)
--------------- ---------------
Gestión de Procesos 57
Implementación de la Exclusión Mutua ( Semáforos )
Precisando la semántica:
P.Bajar (S)  IF Valor(S) > 0 THEN
Valor (P.Bajar(S)) = Valor(S) – 1
ELSE
P deja UCP y se bloquea esperando P’.Subir(S)

P.Subir(S)  IF Hay_algun_Pi_esperando_en (S) THEN


Sacar a uno de ellos de espera
INDETERMINISMO
Proceso continuado
Proceso que coge UCP
JUSTICIA
ELSE
Valor (P.Subir(S)) = Valor (S) + 1

Gestión de Procesos 58
Implementación de la Exclusión Mutua ( Semáforos )
Esbozo de implementación:
S Pi Pj Pk
private type Semaforos is record 0
valor : NATURAL;
cola : unaCola;
end record; ¿Dónde están los semáforos?
Hacen falta operaciones del estilo: crear, conectarse, destruir
procedure Inicializar (S : out Semaforos;
valor : NATURAL) is
begin Exclusión mutua, Salvado estado Pi
S.valor := valor;
end Inicializar; Dispatcher

Gestión de Procesos 59
Implementación de la Exclusión Mutua ( Semáforos )
procedure Bajar (S: in out Semaforos) is begin
if S.valor = 0 then
encolar (ejecutandose, S.cola);
planificar;
else S.valor := S.valor - 1; endif;
end Bajar;

procedure Subir (S: in out Semaforos) is begin


if S.cola.primero /= 0 then
encolar (sacarProceso(S.cola), preparados);
planificar;
else S.valor := S.valor + 1; endif;
end Subir;
Gestión de Procesos 60
Implementación de la Exclusión Mutua ( Semáforos POSIX )

int sem_init (sem_t *S, int global, unsigned int valor)

int sem_wait (sem_t *S)

int sem_post (sem_t *S)

int sem_destroy (sem_t *S)

Gestión de Procesos 61
Paso de mensajes
Debilidades del Sincronismo + Memoria Común:
• Primitivas de bajo nivel (Inhibir Interrupciones, TASL, Semáforos)
• Inviable en sistemas débilmente acoplados sin memoria común

Solución: Envío y recepción de mensajes


----- -----
Escribe ----- Porg P ----- 11
----- dst -----
Enviar (Pdst, msj) Recibir (Porg, msj)
----- Lee
11 -----
-----
Primera aproximación a la
sintaxis:
void enviar ( int Pdestino, ? void recibir ( int Porigen,
char * msj ); char * msj );
int int

Gestión de Procesos
¿Puede fallar enviar/recibir? ? 62
Paso de mensajes ( Ejemplos de uso: cuentaParMsj.c )
• ¿Cómo podría ser cuentaPar.c si no hay memoria común?

620… 067… 625… 217… maestro


1 3 2 2 620… 067… 625… 217…

+
1
8 3 2 2
esclavo1 esclavo2 esclavo3 esclavo4
620… 067… 625… 217…

• El vector lo tiene un proceso “maestro”

• El maestro: reparte “envía” trabajo a los “esclavos” y


Gestión de Procesos recoge “recibe” resultados 63
Paso de mensajes ( Ejemplos de uso: cuentaParMsj.c )
maestro
#define longRodaja (N/4)
int vector[N], iRodaja;
int veces, vecesLocal; esclavo

#define longRodaja (N/4)


// Repartir trabajo
iRodaja = 0; int rodaja[longRodaja];
for e in 1..4 { int veces;
enviar (e, &vector[iRodaja],
longRodaja);
iRodaja += longRodaja; recibir (0, rodaja,
} longRodaja);
veces = contarEn (rodaja);
// Recoger resultados enviar (0, &veces, 1);
veces = 0;
for e in 1..4 {
recibir (e, &vecesLocal, 1);
veces += vecesLocal;
}
Gestión de Procesos 64
Paso de mensajes (muchas semánticas)
-----
----- ? -----
-----
----- -----
Po env (Pd, msj) ? rec (Po, msj) Pd ¿Bloqueo?
Po ----- -----
----- -----
----- -----

• ¿Bloqueo? El bloqueo dependerá de la  |  de mensajes


• ¿Recibió Pd?  msj  Se le entrega a Pd y continua
 msj  Se bloquea a Pd hasta
Independencia del
enlace de Tiempo Real
No siempre
comunicación Tolerancia a Fallos

int recibir ( int Porg, char * msj, • Bloquear 


int TmaxEsp) • Bloquear un máximo 7

Gestión de Procesos
• No Bloquear 0 65
Paso de mensajes (Cuestiones de Diseño)

• Mensajes de longitud fija vs variable


• Capacidad de almacenamiento 0 ..

• Envío por copia vs referencia
• Comunicación Directa vs Indirecta
Simétrica vs Asimétrica Unidireccional vs Bidireccional

Pi Pj Pi B Pj
Gestión de Procesos 66
Paso de mensajes (Mensajes de longitud fija vs variable)

• Longitud Fija
El S.O. La aplicación
siempre envía distingue
el total distintos msj.
Simplifica la gestión de la capacidad de almacenamiento del canal

• Longitud Variable
El S.O. envía 110 Mensaje de
lo que diga la 110 bytes
aplicación aj e
e n s
prop io m
En el
¿Cómo? En la llamada
enviar (Pdest, msj, 110)
Gestión de Procesos 67
Paso de mensajes (Mensajes de longitud fija vs variable)
MINIX 3

m_source m_source m_source m_source


typedef struct {
m_type m_type m_type m_type
int m_source;
m1_i1 m2_i1 m3_i1 m4_i1
int m_type;
m1_i2 m2_i2 m3_i2 m4_i2
union {
m1_i3 m2_i3 m3_p1 m4_i3
mess_1 m_m1;
m1_p1 m2_l1 m4_i4
mess_2 m_m2;
m1_p2 m2_l2 m4_i5
m3_ca1
mess_3 m_m3;
m1_p3 m2_p1
mess_4 m_m4;

mess_5 m_m5;
40
69 mess_7 m_m7;
Práctica 4: Nueva llamada SO 84
mess_8 m_m8;
Proceso40.if (proceso_vivo(84)
} m_u;
68
# Llamada 69 } message;
Paso de mensajes (Capacidad de almacenamiento 0..)
Ilimitada () Nula (0)
Po Pd Po Pd
¡Nunca Bloqueo! ¡Siempre Bloqueo!
Po Pd Po Pd
Espera a Pd.recibir
Limitada (8)
Po Pd Po Pd
Cita “Rendez-vous”
Hueco  Sin Bloqueo
Po Pd Po Pd

• Bloqueo Comunicación Síncrona


¡No hay Hueco!
• Sin Bloqueo
Po sabe que Pd recibió
Estado = Lleno
Comunicación Asíncrona ¿Y aquí?
Gestión de Procesos 69
Paso de mensajes (Envío por copia vs referencia)

Escribir
-----
----- Po Pd
-----
env (Pd, msj) rec (Po, msj)
Leer
-----
1 2 -----
-----
¡ 2 copias extra por cada envío/recepción !
Envío por referencia
pedirBuffer
Escribir
----- Po Pd
-----
----- rec (Po, msj)
env (Pd, msj)
• Complejidad pedir/liberar Buffer Leer
-----
• ¿Y si no hay memoria común? -----
-----
• ¿Seguridad? liberarBuffer
Gestión de Procesos 70
Paso de mensajes (Comunicación Directa)
• A qué proceso se desea enviar
Indicación explícita
• De qué proceso se desea recibir

¿15.731 es primo?
Cliente Servidor

repeat Simétrica repeat


read (msjp.num); recibir ( Pc, &msjp);
enviar (Ps, &msjp); enviar ( Pc,
recibir (Ps, &msjr); respuesta(msjp))
imprimir (msjr.esPrimo) forever
forever Simétrica

Gestión de Procesos 71
Paso de mensajes (Comunicación Directa “Características”)
• Creación automática del enlace Po Pd
• Necesidad de conocer los Pid’s de los procesos Tipo de
• De Pi a Pj SÓLO un enlace en cada sentido mensaje
0
15.731
esPrimo?
Cliente Servidor Cliente ? Servidor
Hora?
1
¿Todo resuelto?
H P P P P P P P
Cliente Servidor

• Un enlace asocia SÓLO a dos procesos

Gestión de Procesos 72
Paso de mensajes (Un enlace asocia SÓLO a dos procesos)

C1 C1
S S
C2 C2

Servidor
repeat
• Inanición
if recibir (PC1, &msjp , 1 ) then
enviar (PC1, respuesta (msjp)); • Espera Activa
Mitigada?
elsif recibir (PC2, &msjp , 1 ) then
enviar (PC2, respuesta (msjp)); • 50 Clientes????
forever
! Demasiadas pegas ¡
Gestión de Procesos 73
Paso de mensajes (Comunicación Directa Asimétrica)
Mejor admitir un recibir de cualquier proceso (no uno concreto)

int recibir (char * msj)


C1 equivalentes
S Pid del proceso remitente
C2
int recibir (int * remitente, char * msj)

• ¿Más de un servidor?
Servidor
repeat
S1
remitente := recibir (&msjp);
C
enviar (remitente, respuesta (msjp)); S2
forever
int enviar (char * msj)
Pid del proceso que recibió???
Gestión de Procesos 74
Paso de mensajes (Comunicación Indirecta)
enviar (buzon, msj) recibir (buzon, msj)
PC1 PS1
bPeti bPeti
PC PS
PCn PSm
NM 11

¿De quién
PS1 PC1 recibí?
bPeti bPeti
PC PS
PSm PCn
1M N1 PCn
• Indeterminismo PCn
¿Quién recibe? • Justicia
• Integridad int recibir (buzon, msj)
Gestión de Procesos 75
Paso de mensajes (Comunicación Indirecta)
Los enlaces pueden ser Unidireccionales o Bidireccionales
PC1
PC PS PS
PC2
¿ Problemas ? ¿ Y aquí ?
Lo normal Unidireccionales: Lo más general:

bPeti P1 B1
PS1 P4
PC P2
PS2 P5
bResp P3 B2

• Varios Procesos
¿ Código del Cliente y de • Varios Buzones
los Servidores ?
• Todo dinámico
Gestión de Procesos 76
Paso de mensajes (Comunicación Indirecta)
Un modelo: Capacidad
type Buzones is private;

* function Crear (nombreB: Nombres ) return Buzones;


function Conectarse (nombreB: Nombres) return Buzones;
procedure Enviar (b: in out Buzones; msj: Mensajes);
procedure Recibir (b: in out Buzones; msj: out Mensajes);

* procedure Destruir (b: in out Buzones);


*mqd_t
 mq_open (const char
Propietario *name, int
Excepción  oflag, …)
buzonInexistente, ...
POSIX
int mq_send (mqd_t mqid, const char
• *msgptr, size_t msgsz, unsigned msgprio)
Mensajes en el buzón
¡ssize_t
Problemática Destrucción
mq_receive ! char
(mqd_t msid, • Procesos
*msgp, size_t msgsz, unsigne
bloqueados
*msgprio)
• Referencias a buzones destruidos
intGestión
mq_close (mqd_t mqid)
de Procesos 77
Planificación de Procesos ( Criterios )
Planificar  Elegir el siguiente Pi a ejecutar
Criterios ?
• JUSTICIA Pi
?
• EFICIENCIA
• RENDIMIENTO Carga Tiempo
• MINIMIZAR TIEMPOS Sin CPU de
Ejecutándose Retorno
Tiempo de Espera
¿Tiempo de Respuesta?
CPU
Pi

<cr>
Criterios difícilmente alcanzables:
Tiempo inútil Tiempo
Gestión de Procesos útil Favorecer Pi  Perjudicar Pj 78
Planificación de Procesos ( PCPU vs PE/S )

PCPU

Periodos cortos de CPU


? Periodos largos de CPU

PE/S

Abandona voluntariamente la UCP

¿Cómo reconocerlos? TCPU / TE/S

PCPU 10,1 / 3,1 => 3,26


PE/S 2,9 / 9,8 => 0,30
Gestión de Procesos 79
Planificación de Procesos ( Por niveles )

Planificación a Planificación a
corto plazo CPU medio plazo
Memoria
S.O.
CPU T2
T1, T2,
IT2 T3 Entrada al
T3, T4,
T5 sistema
T5, T6

frecuencia alta frecuencia baja

Gestión de Procesos 80
Planificación de Procesos ( Políticas )
Sistemas Batch
• No expulsores o expulsores con un quantum grande
• Reducen cambios de contexto y mejoran el rendimiento
• Primero en llegar primero en servir FCFS,
Más corto el siguiente SJF,
Tiempo restante menor SRTN
Sistemas interactivos
• Expulsores: evita la monopolización de la CPU
• Round-Robin, prioridades, múltiples colas,
Más corto el siguiente SPN (envejecimiento)
Sistemas de tiempo real
• Monotónico en frecuencia
• Deadline más próximo el siguiente

Gestión de Procesos 81
Planificación de Procesos ( Primero en llegar FCFS )
Sólo cuando un proceso abandona voluntariamente la CPU, la
misma se asigna al proceso que lleva más tiempo preparado (FIFO)

D C B A D C B A D C B

A E/S

Sencillo, pero  Ausencia de política

Tesp 9 {PE/S}n PUCP


D C B A
4 4 4 8 Tret 14 T<
T >>
Tesp 6 PE/S {PE/S}n-1
A D C B
E/S
8 4 4 4 Tret 11 “Efecto
Gestión de Procesos convoy” PUCP 82
Planificación de Procesos ( Criterios )

preparados
D, C, B, A CPU

Proceso TiempoCPU T_Espera T_Retorno


A 8 0 8
B 4 8 12
C 4 12 16
D 4 16 20
Sumas 36 56
T_Medios 9 14

Gestión de Procesos 83
Planificación de Procesos ( Efecto convoy )
PUCP = {10UCP + 2E/S}* PE/S = {1UCP + 2 E/S}*

PE/S

PUCP
CPU al 100%, pero tan sólo 30 unidades de tiempo en E/S

PE/S
??
PUCP
CPU al 100% y además, 55 unidades de tiempo en E/S

Gestión de Procesos 84
Planificación de Procesos ( El más corto primero SJF )
Objetivo: Minimizar Tesp/ret 4
8 3 8 5 4 3
5 CPU
¿Óptimo?
¿Dónde esperan los procesos?
1

¿Aplicable SJF en
preparados planificación a largo y a
CPU
corto plazo?

¿Más corto? ¿Más corto? Sistemas


interactivos
• Tiempo total de CPU
Contraejemplo C(1)
• Lo declara el usuario
A(2) D(1)
• Si engaña  KILL B(4) E(1)

0 1 2 3 4
Gestión de Procesos 85
Planificación de Procesos ( Tiempo restante menor SRTN )

• Variante expulsora del SJF.

• Cuando llega un trabajo nuevo, comparar su petición de


tiempo
con el tiempo que le queda al actual. Seleccionar el menor.
• Favorece a los trabajos nuevos

C(1)
A(2) D(1) ¿Tiempo medio de espera?
B(4) E(1)

0 1 2 3 4 5 6 7

Gestión de Procesos 86
Planificación de Procesos (Round Robin)
“Todos iguales”: Turno Rotatorio o Rodajas de Tiempo
• A cada Pi que pasa a ejecución se le dá una rodaja “cuanto” de tiempo
a La consume totalmente b La usa parcialmente y abandona
y se le expulsa voluntariamente la UCP

Pi Pi Ley del 80%


rodaja
sleep, wait, exit
• Política FIFO de gestión de la cola de preparados
• Dos cuestiones de diseño:
1 ¿Cómo elegir el tamaño de la rodaja?
2 ¿Cómo determinar el fin de rodaja?
Gestión de Procesos 87
Planificación de Procesos (Round Robin)
1 ¿Cómo elegir el tamaño de la rodaja? Sea Tcc = 5 mseg (mucho)
a Rodaja pequeña 20 mseg => Burocracia del 20%
b Rodaja grande 500 mseg => Burocracia del 1%
UCP útil Mejor
Respuesta lenta a
usuarios interactivos
¿Degenera en FCFS? interactividad

• Ejemplo: P1, P2, P3 => 24, 3 y 3. Rodajas 4 vs 12 y Tcc = 0,5


MINIX3 4 tics
66,6mseg
P1 P2 P3 P1 P1 P1 P1 P1
Valores comunes:
P1 P2 P3 P1 20..50 mseg

31,5 33,5
Gestión de Procesos 88
Planificación de Procesos (Round Robin)
2 ¿Cómo determinar el fin de rodaja?
¿Somos justos con P3?
a Una interrupción periódica • Dar 2 rodajas
• Resetear interrupción
P1 P2 P3 P4
sleep
¿viable? F(int) en 68901 [1µseg..20mseg]
1GHz
b Sumar ticks de una interrupción más frecuente 32bits
P1 P2 P3 P4
sleep

Gestión de Procesos 89
Planificación de Procesos (Prioridades) á x0
m N
“Unos más importantes que otros”: Cada Pi prioridad explícitam
no ín N 0
s or a expu
p ul lsora
e x
P7 P7
P3 P3
P1 P1

UCP siempre ejecuta Pi más prioritario UCP libre  ejecutar Pi más prioritario

• Igualdad de prioridad  FCFS, Round Robin


• Prioridades estáticas vs dinámicas
P9
Sencillo pero inanición P7
P3
¿ tiempo real ? P1
Gestión de Procesos 90
Planificación de Procesos (Prioridades dinámicas)
a Evitar la inanición: ¿ Favorece a los trabajos cortos ?
Disminuir la prioridad a medida que se usa la UCP
Aumentar la prioridad si se está tiempo en preparados

b PE/S vs PUCP Favorece a los Pi ligados a E/S

• ¿Cuáles son PE/S? PE/S aquellos que usen una parte


• ¿Todo el tiempo será PE/S? menor de la rodaja de UCP

Ejemplo con rodajas de 100 mseg:


P1 usa 2 mseg de UCP  PE/S Prio (P1) = 100/2 = 50
P2 usa 25 mseg de UCP  PUCP Prio (P2) = 100/25 = 4
Estáticas muy bajo  16
¿Rango de prioridades [0..N]?
Gestión de Procesos Dinámicas muy variable 91
Planificación de Procesos (Múltiples colas)
“Mezcla de políticas”: Cada Pi asociado a una cola de forma estática

Prioridad ¿Expulsora?
3 FCFS
Quantum
2 4
Round
1 Robin 8

0 16

Dos elecciones:
1 Seleccionar cola
2 Seleccionar proceso dentro de la cola
Gestión de Procesos 92
Planificación de Procesos (Múltiples colas realimentadas)
“Mezcla de políticas”: Cada Pi asociado a una cola de forma dinámica
a Menos Cambios de Contexto b Favorecer selectivamente PE/S
Prioridad + Rodajas Variables Prioridad
4 1 3 Terminal

3 2 2 E/S

2 4
1 Rodaja corta
1 8
0 Rodaja larga
0 16
Consumir rodajas:
Rodajas para Pi  1, 2, 4, 8, 16 Bajar de prioridad
Gestión de Procesos 93
Planificación de Procesos (MINIX 3)
Preparados

MinPrioridad
Pi
sched
SI consumió su rodaja
Nueva rodaja
Prioridad++ ¡Menor!
RoundRobin Encolar_Al_Final
SINO
Encolar_Al_Principio

MaxPrioridad

/usr/src/kernel/proc.h proc[log].p_nextready

94
Planificación de Procesos ( Pi más corto siguiente SPN )

preparados Tiempo de próxima


CPU posesión de UCP

¿Más corto? SJF ¿Más corto?SPN


? Predicción

¿Predicción? (i)  i+1 = F (ti, i)


i+1 =  ti + (1- ) i y  = 1/2
ti  6 4 6 4 13 13 13

Gestión de Procesos
i  10 8 6 6 5 9 11 12
95
Planificación de Procesos ( Sistemas de Tiempo Real )

Hard real time vs Soft real time

Eventos: periódicos vs aperiódicos

Dado
• m eventos periódicos
• evento i ocurre en el periodo Pi y precisa Ci segundos
El sistema es planificable si
m
Ci
i1 P  1
i
(Leer las secciones 7.4.2, 7.4.3 y 7.4.4)
Gestión de Procesos 96
Planificación de Procesos ( Política vs Mecanismo )

Separar qué se puede hacer de cómo hacerlo


• Un proceso puede saber cuáles de sus threads hijos son
los más importantes y asignarles prioridad

Algoritmo de planificación parametrizado


• Mecanismo en el kernel

Los procesos de usuario ponen el valor de los parámetros


• Los procesos de usuario indican la política

pthread_attr_setschedpolicy(…) => FIFO, RR, OTHERS

Gestión de Procesos 97
Planificación de Threads ( Espacio de usuario )

Quantum por proceso de 50 mseg


Cada thread ejecuta 5 mseg de ráfaga de CPU
Gestión de Procesos 98
Planificación de Threads ( Espacio de kernel )

Quantum por proceso de 50 mseg


Cada thread ejecuta 5 mseg de ráfaga de CPU
Gestión de Procesos 99
Sistemas multiprocesador

µP1 µP2 µP3 µP4 Cada µP su cola

Peligro de carga desequilibrada

Planificar  ¿Qué thread? ¿En qué núcleo?

1. Tiempo compartido Threads independientes Cola única

No escalable con aumento núcleos


µP1 µP2 µP3 µP4
Espera activa si FR  Spin Lock
¡Estoy en RC!  Alarga rodaja

¡ Ojo !  Spin Lock Problemática caches  Afinidad


Gestión de Procesos 100
Sistemas multiprocesador
Ordenando 128.000 claves “burbuja” en Intel Core 2 Quad Q6600 2,46GHz

µP0 µP1 µP2 µP3

4MB L2 4MB L2

sched_setaffinity

Gestión de Procesos 101


Sistemas multiprocesador
2. Espacio compartido Threads cooperantes Apropiarse {µP}n

Núcleo ocioso cuando Pi.bloqueado


Sin multiprogramación  ¡Menos burocracia!
Sin “n” núcleos libres no me ejecuto

Servidor Web con {threads} variable


Gestión de Procesos 102
Sistemas multiprocesador
3. Planificar por pandillas Threads cooperantes
Tiempo/Espacio

Espacio
compartido
Tiempo
compartido
FIN
Gestión de Procesos 103

También podría gustarte