13 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, … (Gp:) 1 (Gp:) 2 (Gp:) 3 (Gp:) 4 (Gp:) 97 (Gp:) 98 (Gp:) 99 (Gp:) 100 (Gp:) 50 (Gp:) type descriptorProceso is record pid: NATURAL; estado: unEstado; sig: idProceso; lapso: NATURAL; end record; espLapso : unaCola;
(Gp:) 10 (Gp:) 5 (Gp:) 25
El campo sig me sigue sirviendo para encadenar Otras formas de implementarlo: (Gp:) 5 (Gp:) 5 (Gp:) 15 (Gp:) 4 (Gp:) 50 (Gp:) 97
14 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 record pid: NATURAL; padre: idProceso; estado: unEstado; sig: idProceso; lapso: NATURAL; end record; El Padre (P) hace wait (H): — Localizar H en procesos => h if h.estado = zombie then Liberar recursos del Hijo y continuar al Padre else — hijo vivo p.estado:=espFinHijo; p.sig:=h; liberar CPU; Un Hijo(H) termina exit: If (p.estado = espFinHijo) & (p.sig = h) then liberar recursos Hijo y continuar Padre else h.estado := zombie y liberar CPU
15 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 record pid: NATURAL; padre: idProceso; estado: unEstado; sig: idProceso; lapso: NATURAL; SP: address; memoria: ———-; ficheros: ———-; tiempos: ———-; end record; type unaCola is record primero: idProceso := 0; ultimo: idProceso := 0; end record; procesos : array [1..maxProcesos] of descriptorProceso; ejecutandose: idProceso; preparados, espLapso: unaCola; ¿ fork y exec ?
16 Campos en una entrada a la tabla de procesos Esbozo de implementación ( Otro ejemplo )
17 Esbozo de implementación ( El Cambio de Contexto ) Causas? (Gp:) Llamada al Sistema Fin de Proceso Bien/Mal Interrupción
(Gp:) Trap (Gp:) (E/S, F.R.)
(Gp:) Mecanismo similar
Supongamos como causa "Fin de Rodaja" (Gp:) ejecu- tándose (Gp:) Pi
(Gp:) Hw (Gp:) (1)
(1) Reconocimiento de la interrupción (Gp:) S.O.
(Gp:) Pj
(Gp:) Ens. (Gp:) (2)
(2) Salvar reg (Pi) y conmutar de pila (Gp:) C/Modula/Ada (Gp:) (3)
(3) 1 Recorrer dormitorio 2 Elegir siguiente proceso (Gp:) Ens. (Gp:) (4)
(4) Recuperar reg (Pj) y cederle control (Gp:) Planificador
(Gp:) Dispatcher
¿No hay procesos preparados?
18 (Gp:) Vector de Interrupciones (Gp:) S.O.
Esbozo de implementación ( El Cambio de Contexto ) ———- ———- sleep(10) ———- ———- exit(0) ——- ——- ——- ——- ——- ——- ——- ——- ——- ——- ——- ——- (Gp:) TRAP #0
——- ——- ——- ——- ——- (Gp:) INT 3
———- divu d5,d0 ———- ——- ——- ——- ——- ——- (Gp:) DIV 0
(Gp:) Se salva el SR y PC
(Gp:) ——- ——- ——- ——- ——- ——- ——- ——- (Gp:) Cambio de contexto
19 Threads ( Visión abstracta ) Modelo de procesos más común ? Espacios de direcciones disjuntos (Gp:) Registros Código Datos, Pila Ficheros (Gp:) Pi
(Gp:) Registros Código Datos, Pila Ficheros (Gp:) Pj (Gp:) fork (Gp:) exec (Gp:) ls.exe
Facilita protección Pi?Pj, pero: Creación laboriosa Cambio de contexto pesado (procesador + entorno) TLB's, cachés, … Comunicación vía mensajes más seguro pero más lento ¿Y si los procesos son cooperantes? Objetivo común Colaboración vs agresión Protección más laxa Pueden desear mantener datos comunes con los menores costes de tiempo
20 (Gp:) BD utilidades
Threads ( Visión abstracta ) Procesos Ligeros ? Espacios de direcciones no disjuntos (Gp:) Registros Pila (Gp:) Registros Pila (Gp:) Código, Datos Ficheros (Gp:) Ti (Gp:) Tj
Servidor de localización de utilidades (Gp:) C1 (Gp:) C2 (Gp:) Cn (Gp:) S
(Gp:) consulta
(Gp:) alta
(Gp:) consulta
(Gp:) petición
respuesta (Gp:) petición
(Gp:) petición
¡ Muy eficaz con multiprocesadores ! Soportados de dos formas: En el espacio del S.O. En el espacio del Usuario Biblioteca
21 Threads ( "Linux" ) int __clone (int (*fn) (void *arg), void *child_stack, int flags, void *arg) (Gp:) Como fork sólo que crea un Thread "Específico de Linux" Thread soportado como tal por el S.O. (no portable)
(Gp:) 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 ?
22 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;
pthread_create(&tA, NULL, A, NULL); pthread_create(&tB, NULL, B, NULL); pthread_join (tA, NULL); pthread_join (tB, NULL); exit (0); } void *B (void *basura) { datoB = 2000; sleep (5); printf ("datoA=%dn", datoA); pthread_exit (NULL); } void *A (void *basura) { datoA = 1000; sleep (5); printf ("datoB=%dn", datoB); pthread_exit (NULL); } (Gp:) datoC=0; (Gp:) int datoC; (Gp:) int datoC; (Gp:) ?
Threads ( Ejemplos de uso: cuentaPar.c ) cuentaPar.c: Número de apariciones de un número en un vector (Gp:) 6 2 0 7 4 9 3 4 9 8 0 6 7 9 6 0 6 7 9 8 6 2 5 2 6 4 7 9 3 5 2 1 7 3 2 6 6 4 4 0 (Gp:) const N = 40; objetivo = 6; numCPUs = 4; var vector array[1..N] of integer;
¿ Algoritmo paralelo ? (Gp:) T0 (Gp:) T1 (Gp:) T2 (Gp:) T3
(Gp:) 1 (Gp:) 3 (Gp:) 2 (Gp:) 2
(Gp:) + (Gp:) 8
23
(Gp:) int longRodaja, numVecesLocal[MAX_ESCLAVOS], *vector;
void *esclavo (void *parametro) { ….. }
int main (int argc, char *argv[]) { int i, numVeces, cardinalidad = atoi (argv[1]); int numEsclavos = atoi (argv[2]); pthread_t pids[MAX_ESCLAVOS];
// Pedir memoria e inicializar vector
// Crear esclavos y esperar a que terminen su trabajo for (i = 0; i < numEsclavos; i++) pthread_create (&pids[i], NULL, esclavo, (void *) i); for (i = 0; i < numEsclavos; i++) pthread_join (pids[i], NULL);
// Sumar los valores de todos e informar del resultado numVeces = numVecesLocal[0]; for (i = 1; i < numEsclavos; i++) numVeces = numVeces + numVecesLocal[i]; printf ("Veces que aparece = %dn", numVeces); }
(Gp:) %cuentaPar 1000000 4
Threads ( Ejemplos de uso: cuentaPar.c ) 24
// Variables globales int longRodaja, numVecesLocal[MAX_ESCLAVOS], *vector;
void *esclavo (void *parametro) { int yo, inicio, fin, i, j, numVeces;
yo = (int) parametro; inicio = yo * longRodaja; fin = inicio + longRodaja;
// Buscar en mi parte del vector numVeces = 0; for (i = inicio, i < fin; i++) if (vector[i] == NUM_BUSCADO) numVeces++; numVecesLocal[yo] = numVeces; pthread_exit (NULL); } 25 Threads ( Ejemplos de uso: cuentaPar.c )
(Gp:) 5 (Gp:) 1,286 (Gp:) 4,26 (Gp:) 0,85 (Gp:) 6 (Gp:) 1,127 (Gp:) 4,86 (Gp:) 0,81 (Gp:) 7 (Gp:) 1,113 (Gp:) 4,92 (Gp:) 0,70 (Gp:) 8 (Gp:) 0,998 (Gp:) 5,49 (Gp:) 0,69
(Gp:) cuentaPar 400.000.000 1..8 // Recorriéndolo diez veces (Gp:) 2 Xeon E5520 Quad 2,26GHz . 8ML3 . 12GB . 500GB
Threads ( Ejemplos de uso: cuentaPar.c ) 26 (Gp:) Esclavos (Gp:) Tiempo (Gp:) Aceleración (Gp:) Eficiencia (Gp:) 1 (Gp:) 5,480 (Gp:) 2 (Gp:) 2,721 (Gp:) 2,01 (Gp:) 1,01 (Gp:) 4 (Gp:) 1,408 (Gp:) 3,89 (Gp:) 0,97 (Gp:) An = T1 / Tn (Gp:) En = An / n
sortPar.c: Ordenar un vector en memoria (Gp:) 3 8 15 2 4 1 7 10 6 14 13 5 11 9 12 16 (Gp:) T0 (Gp:) T1 (Gp:) T2 (Gp:) T3
(Gp:) 2 3 8 15 1 4 7 10 5 6 13 14 9 11 12 16
(Gp:) ordenar
(Gp:) 1 2 3 4 7 8 10 15 5 6 9 11 12 13 14 16
(Gp:) T0 (Gp:) T2 (Gp:) mezclar
(Gp:) T0 (Gp:) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 (Gp:) mezclar
Threads ( Ejemplos de uso: sortPar.c ) 27
sortPar.c: Ordenar un vector en memoria [Refinamiento] (Gp:) A (Gp:) B (Gp:) C (Gp:) D (Gp:) E (Gp:) F (Gp:) G (Gp:) 0 (Gp:) 1 (Gp:) 2 (Gp:) 3 (Gp:) 0 (Gp:) 2 (Gp:) 0
esclavo (yo: integer);
ordenarRodaja(yo); case yo of 0: mezclar(A,B,E); mezclar(E,F,G); 1: ; 2: mezclar(C,D,F); 3: ; end; ? (Gp:) La mezcla es destructiva => vector auxiliar (Gp:) Va (Gp:) Va (Gp:) Vb (Gp:) Va
Mezclar requiere haber ordenado . => semáforos Threads ( Ejemplos de uso: sortPar.c ) 28 sem_init sem_wait sem_post
#define MAX_ENTERO 10000 #define MAX_ESCLAVOS 4 // Solo funciona con 4 esclavos
//————– VARIABLES GLOBALES ——————————- int cardinalidad, longRodaja; int *vector, *vectorBis; sem_t S1a0, S3a2, S2a0;
void imprimir (int *vector) { int i;
printf ("Contenido del vectorn"); printf ("====================n"); for (i=0; i< cardinalidad; i++) { printf ("%6d ", vector[i]); if ((i%10) == 0) printf ("n"); } printf ("n"); }
void mezclar (int i, int longRodaja, int *vOrg, int *vDst) { int iDst, iTope, j, jTope;
iTope = i + longRodaja; j = iTope; jTope = j + longRodaja; for (iDst = i; iDst < jTope; iDst++) { if (i == iTope ) vDst[iDst] = vOrg[j++]; else if (j == jTope ) vDst[iDst] = vOrg[i++]; else if (vOrg[i] < vOrg[j]) vDst[iDst] = vOrg[i++]; else vDst[iDst] = vOrg[j++]; } } Threads ( Ejemplos de uso: sortPar.c ) 29
void *esclavo(void *parametro) { int yo, inicio, fin, i, j, imenor, menor; int unCuarto, unMedio;
yo = (int) parametro; inicio = yo * longRodaja; fin = inicio + longRodaja; unMedio = cardinalidad / 2; unCuarto = cardinalidad / 4;
// Ordenar por insercion directa for (i = inicio; i < fin; i++) { imenor = i; menor = vector[i]; for (j = i; j < fin; j++) if (vector[j] < menor) { imenor = j; menor = vector[j]; } vector[imenor] = vector[i]; vector[i] = menor; }
// Fase de mezclas. Solo valida para 4 esclavos switch (yo) { case 0: sem_wait (&S1a0); mezclar(0, unCuarto, vector, vectorBis); sem_wait (&S2a0); mezclar(0, unMedio, vectorBis, vector); break; case 1: sem_post (&S1a0); break; case 2: sem_wait (&S3a2); mezclar(unMedio, unCuarto, vector, vectorBis); sem_post (&S2a0); break; case 3: sem_post (&S3a2); break; default: printf ("Errorn"); break; } pthread_exit(NULL); } Threads ( Ejemplos de uso: sortPar.c ) 30
int main( int argc, char *argv[] ) { int i, numEsclavos; pthread_t pids[MAX_ESCLAVOS];
cardinalidad = atoi(argv[1]); numEsclavos = MAX_ESCLAVOS; longRodaja = cardinalidad / numEsclavos;
// Pedir memoria e inicializar el vector vector = malloc(cardinalidad * sizeof(int)); vectorBis = malloc(cardinalidad * sizeof(int)); for (i=0; i< cardinalidad; i++) vector[i] = random() % MAX_ENTERO; imprimir(vector);
// Inicializar semaforos para sincronizar sem_init (&S1a0, 0, 0); sem_init (&S3a2, 0, 0); sem_init (&S2a0, 0, 0);
// Crear esclavos y esperar a que terminen su trabajo for (i=0; i< numEsclavos; i++) pthread_create (&pids[i], NULL, esclavo, (void *) i); for (i=0; i< numEsclavos; i++) pthread_join (pids[i], NULL);
imprimir(vector); return (0); } sort 200000 => 8:350 sortPar 200000 => 2:100 Threads ( Ejemplos de uso: sortPar.c ) 31
32 pthread_create pthread_join pthread_exit pthread_self Threads ( En el espacio de usuario ) (Gp:) El S.O. no los soporta Cambio contexto rápido Distintos planificadores
(Gp:) read, . ¡ Bloqueantes ! Falta de página ¡Planificación expulsora!
33 Threads ( En el espacio del S.O. ) (Gp:) ?
34 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 A antes que B (Gp:) Canal de Panamá
Tortilla 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
35 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 El empresario y los taxistas: (Gp:) ¡Que buen negocio!
(Gp:) ¡Me tangan!
36 Condiciones de Carrera (Modelización con threads) Ingreso de Taxista 1 = 80729 Ingreso de Taxista 2 = 80618 Total recaudacion = 161096 (Gp:) + (Gp:) 161347
(Gp:) 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 = %dn", cuenta); return (0); }
37 (Gp:) Ingreso
Condiciones de Carrera (Modelización con threads) void *taxista (void *parametro) { // Variables recaudacion = 0; mio = 0; do { espera = random() % MAX_ESPERA; for (i=1; i< espera; i++); 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 = %dn", yo, recaudacion – mio); pthread_exit (NULL); } (Gp:) Hacer Carrera
(Gp:) Buscar Cliente
38 Condiciones de Carrera (Modelización con threads) (Gp:) Threads (Gp:) pc1:4Cores (Gp:) pc9:8Cores (Gp:) 2 (Gp:) 4 (Gp:) 8 (Gp:) 16 (Gp:) 32 (Gp:) Fallos x 1.000 (Gp:) 7 (Gp:) 64 (Gp:) 230 (Gp:) 533 (Gp:) 830 (Gp:) 207 (Gp:) 926 (Gp:) 1.000 (Gp:) 1.000 (Gp:) 1.000
39 3: cuenta := cuenta + importe Condiciones de Carrera (El problema) (Gp:) 3.1: PUSH importe 3.2: PUSH cuenta 3.3: ADDP 3.4: POP cuenta
3.1, 3.2 (Gp:) T1 (Gp:) T2 (Gp:) 5.000 (Gp:) cuenta (Gp:) 10.000 (Gp:) T1.importe
(Gp:) 3.3 (Gp:) 5.000 (Gp:) 10.000 (Gp:) T1.SP
3.1, 3.2 (Gp:) 1.500 (Gp:) T2.importe (Gp:) 3.3 (Gp:) 5.000 (Gp:) 1.500 (Gp:) T2.SP
3.3, 3.4 (Gp:) 15.000
(Gp:) 15.000 (Gp:) cuenta
3.3, 3.4 (Gp:) 6.500 (Gp:) cuenta (Gp:) 6.500
¿problema?
40 Exclusión mutua y Región crítica (La solución) (Gp:) RC (Gp:) RC
(Gp:) Aquí como máximo un Pi
(Gp:) Exclusión Mutua
(Gp:) Integridad Datos Comunes
(Gp:) Aquí cero, uno o más Pi
Los Pi indicarán cuándo EntranEnRC y cuándo SalenDeRC
41 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
42 Implementación de la Exclusión Mutua Mecanismos: Inhibición de interrupciones . Semáforos Cerrojos (espera activa) . Monitores (Gp:) Hw (Gp:) Sw
(Gp:) Lenguaje (Gp:) S.O.
Inhibición de interrupciones Taxistas InhibirInterrupciones cuenta := cuenta + importe PermitirInterrupciones RC muy corta o pueden perderse interrupciones Exclusión total vs parcial DirecciónGeneralDeTráfico repeat aguardarAgazapados y ¡foto! InhibirInterrupciones numeroMultas++ PermitirInterrupciones until cubiertoCupo Sólo válido en monoprocesador Peligroso en manos del usuario Útil dentro del propio S.O.
43 Implementación de la Exclusión Mutua ( Cerrojos ) Una variable "cerrojo" por cada RC distinta que indica Libre/Ocupada (Gp:) Taxistas Entrar (RCTaxistas) cuenta := cuenta + importe Salir (RCTaxistas) (Gp:) Guardia Civil Entrar (RCDGT) numeroMultas++ Salir (RCDGT)
(Gp:) while RCT = ocupada do null; RCT := ocupada cuenta := cuenta + importe; RCT := libre
(Gp:) entrar tst.b RCT bnz entrar move.b #$FF,RCT push importe push cuenta addp pop cuenta salir move.b #$00,RCT
RCT dc.b 0
¡ No funciona !
44 Implementación de la Exclusión Mutua ( El cerrojo falla ) (Gp:) T1 (Gp:) T2 (Gp:) 00 (Gp:) RCT
—————- —————- entrar tst.b RCT —————- —————- tst.b RCT bnz entrar move.b #$FF,RCT —————- —————- (Gp:) T1.SR (Gp:) Z (Gp:) 1
(Gp:) FF (Gp:) RCT
(Gp:) T2 dentro RCT
bnz entrar move.b #$FF,RCT —————- —————- —————- —————- (Gp:) FF (Gp:) RCT
¡¡ T1 también dentro RCT !!
45 Implementación de la Exclusión Mutua ( Un cerrojo seguro? ) (Gp:) El Hw ayuda con una instrucción atómica que consulta y cambia valor (Gp:) tas.b cerrojo, valor
(Gp:) tst.b cerrojo move.b valor,cerrojo
Algoritmos: Dekker, Dijkstra, Knuth, Peterson, ……. (Gp:) entrar tas.b RCT,#$FF bnz entrar push importe push cuenta addp pop cuenta salir move.b #$00,RCT
RCT dc.b 0
(Gp:) F.R.
¿Habrá problemas? (Gp:) No funciona en multiprocesador ya que TAS es ininterrumpible dentro de un procesador, pero supone dos accesos al bus: 1 Lectura del cerrojo 2 Modificación del cerrojo (Gp:) ¡SI!
46 Implementación de la Exclusión Mutua ( Un cerrojo seguro! ) T1 T2 (Gp:) 00 (Gp:) RCT
—————- —————- tas.b RCT,#$FF —————- —————- tas.b RCT,#$FF bnz entrar (Gp:) T1.SR (Gp:) Z (Gp:) 1
(Gp:) FF (Gp:) RCT
(Gp:) FF (Gp:) RCT
bnz entrar ————- ————- ————- ————- T1 en RCT (Gp:) FF (Gp:) RCT
T2 no puede entrar en RC mientras está T1 (Gp:) tas.b RCT,#$FF bnz entrar
47 Implementación de la Exclusión Mutua ( TAS todavía falla! ) TAS ? PedirBus, Leer, PedirBus, Escribir (Gp:) ?P1 ? T1 PB, L1, PB, E1 (Gp:) ?P2 ? T2 PB, L2, PB, E2
(Gp:) ???
(Gp:) ?P1 (Gp:) ?P2 (Gp:) RCT
(Gp:) L1, E1, L2, E2 T1 T2
(Gp:) L2, E2, L1, E1 T2 T1
(Gp:) L1, L2, E1, E2 T1 T2
tas.b RCT,#$FF bnz entrar (Gp:) PH
tasl.b RCT,#$FF bnz entrar ——————— ——————— ¡ Todavía dos problemas ! Espera Activa Inversión de prioridades (Gp:) PL
(Gp:) deadLock
¿ Qué hacer ? (Gp:) TASL "TAS with Lock" ? BusLock, Leer, Escribir, BusRelease (Gp:) ( El Hw nos ayuda )
48 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)? type pthread_mutext_t is record libre : BOOLEAN; cola : unaCola; end record; (Gp:) F (Gp:) RCT (Gp:) Pi (Gp:) Pj
lock (RCT): inhibir interrupciones salvarEstado(ejecutandose) if RCT.libre then RCT.libre = FALSE else meter (ejecutandose, RCT); ejecutandose = planificar(); recuperarEstado(ejecutandose) rte /*Se habilitan interrupciones*/ (Gp:) Multiprocesador (Gp:) ?
tasl (Gp:) ¡ Ojo !
49 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); Bajar (S); — Puede bloquear al proceso (Si Valor = 0) Subir (S); — Puede desbloquear a UN proceso (Gp:) Operaciones Atómicas
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) ————— —————
50 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
51 Implementación de la Exclusión Mutua ( Semáforos ) private type Semaforos is record valor : NATURAL; cola : unaCola; end record; procedure Inicializar (S : out Semaforos; valor : NATURAL) is begin S.valor := valor; end Inicializar; Esbozo de implementación: (Gp:) 0 (Gp:) S (Gp:) Pi (Gp:) Pk (Gp:) Pj
(Gp:) ¿Dónde están los semáforos?
Hacen falta operaciones del estilo: crear, conectarse, destruir (Gp:) Exclusión mutua, Salvado estado Pi
(Gp:) Dispatcher
52 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;
53 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)
54 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 (Gp:) Solución: Envío y recepción de mensajes (Gp:) Porg (Gp:) Pdst (Gp:) Enviar (Pdst, msj) (Gp:) Recibir (Porg, msj)
—– —– —– (Gp:) Escribe
11 —– —– —– —– —– —– 11 (Gp:) Lee
Primera aproximación a la sintaxis: void enviar ( int Pdestino, void recibir ( int Porigen, char * msj ); char * msj ); ¿Puede fallar enviar/recibir? (Gp:) ? (Gp:) ?
(Gp:) int (Gp:) int
Paso de mensajes ( Ejemplos de uso: cuentaParMsj.c ) ¿Cómo podría ser cuentaPar.c si no hay memoria común? (Gp:) 1 (Gp:) 3 (Gp:) 2 (Gp:) 2 (Gp:) 6 2 0 . (Gp:) 0 6 7 . (Gp:) 6 2 5 . (Gp:) 2 1 7 . (Gp:) + (Gp:) 8
(Gp:) esclavo1 (Gp:) esclavo2 (Gp:) esclavo3 (Gp:) esclavo4
(Gp:) maestro (Gp:) 6 2 0 . (Gp:) 0 6 7 . (Gp:) 6 2 5 . (Gp:) 2 1 7 . (Gp:) El vector lo tiene un proceso "maestro"
El maestro: reparte "envía" trabajo a los "esclavos" y recoge "recibe" resultados (Gp:) 6 2 0 . (Gp:) 0 6 7 . (Gp:) 6 2 5 . (Gp:) 2 1 7 .
(Gp:) 1 (Gp:) 3 (Gp:) 2 (Gp:) 2
55
56 Paso de mensajes ( Ejemplos de uso: cuentaParMsj.c ) (Gp:) #define longRodaja (N/4) int vector[N], iRodaja; int veces, vecesLocal;
// Repartir trabajo iRodaja = 0; for e in 1..4 { enviar (e, &vector[iRodaja], longRodaja); iRodaja += longRodaja; }
// Recoger resultados veces = 0; for e in 1..4 { recibir (e, &vecesLocal, 1); veces += vecesLocal; } (Gp:) #define longRodaja (N/4)
int rodaja[longRodaja]; int veces;
recibir (0, rodaja, longRodaja); veces = contarEn (rodaja); enviar (0, &veces, 1); (Gp:) maestro (Gp:) esclavo
57 Paso de mensajes (muchas semánticas) (Gp:) —– —– —– (Gp:) rec (Po, msj) (Gp:) —– —– —– (Gp:) —– —– —– (Gp:) env (Pd, msj) (Gp:) —– —– —–
(Gp:) Pd
¿Bloqueo? (Gp:) El bloqueo dependerá de la ? | ? de mensajes
? msj ? Se le entrega a Pd y continua (Gp:) ? msj ? Se bloquea a Pd hasta
(Gp:) No siempre
(Gp:) Tiempo Real Tolerancia a Fallos
Bloquear Bloquear un máximo No Bloquear (Gp:) int recibir ( int Porg, char * msj, int TmaxEsp)
? 7 (Gp:) 0
(Gp:) ?
(Gp:) ?
(Gp:) Po
¿Bloqueo? (Gp:) ¿Recibió Pd? (Gp:) Po
Independencia del enlace de comunicación
58 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 (Gp:) Pi B Pj (Gp:) Pi Pj
(Gp:) Simétrica vs Asimétrica
(Gp:) Unidireccional vs Bidireccional
59 Paso de mensajes (Mensajes de longitud fija vs variable) Longitud Fija El S.O. siempre envía el total (Gp:) La aplicación distingue distintos msj.
Simplifica la gestión de la capacidad de almacenamiento del canal Longitud Variable El S.O. envía lo que diga la aplicación (Gp:) ¿Cómo?
(Gp:) 110 (Gp:) Mensaje de 110 bytes (Gp:) En el propio mensaje
(Gp:) enviar (Pdest, msj, 110) (Gp:) En la llamada
60 Paso de mensajes (Mensajes de longitud fija vs variable) (Gp:) MINIX 3 (Gp:) typedef struct { int m_source; int m_type; union { mess_1 m_m1; mess_2 m_m2; mess_3 m_m3; mess_4 m_m4; mess_5 m_m5; mess_7 m_m7; mess_8 m_m8; } m_u; } message;
(Gp:) m_source (Gp:) m_type (Gp:) m1_i1 (Gp:) m1_i2 (Gp:) m1_i3 (Gp:) m1_p1 (Gp:) m1_p2 (Gp:) m1_p3 (Gp:) m_source (Gp:) m_type (Gp:) m2_i1 (Gp:) m2_i2 (Gp:) m2_i3 (Gp:) m2_l1 (Gp:) m2_l2 (Gp:) m2_p1 (Gp:) m_source (Gp:) m_type (Gp:) m3_i1 (Gp:) m3_i2 (Gp:) m3_p1 (Gp:) m3_ca1 (Gp:) m_source (Gp:) m_type (Gp:) m4_i1 (Gp:) m4_i2 (Gp:) m4_i3 (Gp:) m4_i4 (Gp:) m4_i5
Práctica 4: Nueva llamada SO Proceso70.if (proceso_vivo(84) (Gp:) 70 (Gp:) 57 (Gp:) 84
(Gp:) # Llamada 57
61 Paso de mensajes (Capacidad de almacenamiento 0..?) (Gp:) Ilimitada (?) (Gp:) Po (Gp:) Pd
(Gp:) Po (Gp:) Pd
¡Nunca Bloqueo! (Gp:) Limitada (8) (Gp:) Po (Gp:) Pd
(Gp:) Po (Gp:) Pd
Hueco ? Sin Bloqueo ¡No hay Hueco! (Gp:) Bloqueo Sin Bloqueo Estado = Lleno
(Gp:) Comunicación Asíncrona
(Gp:) Nula (0) (Gp:) Po (Gp:) Pd
¡Siempre Bloqueo! (Gp:) Po (Gp:) Pd
Espera a Pd.recibir (Gp:) Po (Gp:) Pd (Gp:) Cita "Rendez-vous"
(Gp:) Po (Gp:) Pd
(Gp:) Comunicación Síncrona
(Gp:) Po sabe que Pd recibió
(Gp:) ¿Y aquí?
62 (Gp:) Po (Gp:) Pd
Paso de mensajes (Envío por copia vs referencia) (Gp:) Escribir —– —– —–
(Gp:) env (Pd, msj)
(Gp:) 1
(Gp:) rec (Po, msj)
(Gp:) 2
¡ 2 copias extra por cada envío/recepción ! (Gp:) Leer —– —– —–
(Gp:) Envío por referencia (Gp:) Po (Gp:) Pd
(Gp:) pedirBuffer
(Gp:) Escribir —– —– —–
(Gp:) env (Pd, msj)
(Gp:) rec (Po, msj)
Leer —– —– —– (Gp:) liberarBuffer
Complejidad pedir/liberar Buffer ¿Y si no hay memoria común? ¿Seguridad?
63 Paso de mensajes (Comunicación Directa) (Gp:) Indicación explícita (Gp:) A qué proceso se desea enviar De qué proceso se desea recibir
(Gp:) Cliente (Gp:) Servidor
(Gp:) ¿15.731 es primo?
(Gp:) SÍ
repeat repeat read (msjp.num); recibir ( Pc, &msjp); enviar (Ps, &msjp); enviar ( Pc, recibir (Ps, &msjr); respuesta(msjp)) imprimir (msjr.esPrimo) forever forever (Gp:) Simétrica (Gp:) Simétrica
64 Paso de mensajes (Comunicación Directa "Características") (Gp:) Creación automática del enlace Po Pd
Necesidad de conocer los Pid's de los procesos De Pi a Pj SÓLO un enlace en cada sentido (Gp:) Cliente (Gp:) Servidor (Gp:) esPrimo? (Gp:) Hora?
(Gp:) Cliente (Gp:) Servidor
? (Gp:) 15.731 (Gp:) 0 (Gp:) 1 (Gp:) Tipo de mensaje
¿Todo resuelto? (Gp:) Cliente (Gp:) Servidor
P P P P P P P H Un enlace asocia SÓLO a dos procesos
65 Paso de mensajes (Un enlace asocia SÓLO a dos procesos) (Gp:) C1 (Gp:) C2 (Gp:) S
(Gp:) C1 (Gp:) C2 (Gp:) S
(Gp:) repeat if recibir (PC1, &msjp ) then enviar (PC1, respuesta (msjp)); elsif recibir (PC2, &msjp ) then enviar (PC2, respuesta (msjp)); forever (Gp:) Servidor
Inanición Espera Activa (Gp:) , 1 (Gp:) , 1 (Gp:) Mitigada?
50 Clientes???? ! Demasiadas pegas ¡
66 Paso de mensajes (Comunicación Directa Asimétrica) Mejor admitir un recibir de cualquier proceso (no uno concreto) (Gp:) C1 (Gp:) C2 (Gp:) S
(Gp:) int recibir (char * msj) (Gp:) Pid del proceso remitente
(Gp:) int recibir (int * remitente, char * msj) (Gp:) equivalentes
(Gp:) repeat remitente := recibir (&msjp); enviar (remitente, respuesta (msjp)); forever (Gp:) Servidor
¿Más de un servidor? (Gp:) int enviar (char * msj) (Gp:) Pid del proceso que recibió???
(Gp:) C (Gp:) S1 (Gp:) S2
67 Paso de mensajes (Comunicación Indirecta) (Gp:) bPeti (Gp:) PC (Gp:) PS (Gp:) 1 ? 1
(Gp:) bPeti (Gp:) PC (Gp:) PS1 (Gp:) PSm (Gp:) 1 ? M
(Gp:) bPeti (Gp:) PC1 (Gp:) PCn (Gp:) PS1 (Gp:) PSm (Gp:) N ? M
¿Quién recibe? Indeterminismo Justicia Integridad (Gp:) bPeti (Gp:) PC1 (Gp:) PCn (Gp:) PS (Gp:) N ? 1
¿De quién recibí? (Gp:) PCn
enviar (buzon, msj) recibir (buzon, msj) (Gp:) int recibir (buzon, msj) (Gp:) PCn
68 Paso de mensajes (Comunicación Indirecta) Los enlaces pueden ser Unidireccionales o Bidireccionales (Gp:) PC (Gp:) PS
¿ Problemas ? (Gp:) PC1 (Gp:) PS (Gp:) PC2
¿ Y aquí ? Lo normal Unidireccionales: (Gp:) bPeti (Gp:) PC (Gp:) PS1 (Gp:) PS2 (Gp:) bResp
(Gp:) ¿ Código del Cliente y de los Servidores ?
Lo más general: (Gp:) B1 (Gp:) P2 (Gp:) P4 (Gp:) P5 (Gp:) B2 (Gp:) P3 (Gp:) P1
Varios Procesos Varios Buzones Todo dinámico
69 Paso de mensajes (Comunicación Indirecta) (Gp:) 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); (Gp:) Un modelo:
(Gp:) Capacidad
(Gp:) * (Gp:) * (Gp:) ? Propietario (Gp:) *
Excepción ? buzonInexistente, … ¡ Problemática Destrucción ! (Gp:) Mensajes en el buzón Procesos bloqueados Referencias a buzones destruidos
(Gp:) mqd_t mq_open (const char *name, int oflag, .) int mq_send (mqd_t mqid, const char *msgptr, size_t msgsz, unsigned msgprio) ssize_t mq_receive (mqd_t msid, char *msgp, size_t msgsz, unsigne *msgprio) int mq_close (mqd_t mqid) (Gp:) POSIX
70 Planificación de Procesos ( Criterios ) Planificar ? Elegir el siguiente Pi a ejecutar (Gp:) JUSTICIA EFICIENCIA RENDIMIENTO MINIMIZAR TIEMPOS (Gp:) Criterios
(Gp:) Carga (Gp:) Sin CPU (Gp:) Ejecutándose (Gp:) Pi
(Gp:) Tiempo de Retorno
(Gp:) CPU
(Gp:) Tiempo útil
(Gp:) Tiempo inútil
(Gp:) Tiempo de Espera
¿Tiempo de Respuesta? (Gp:) Pi
(Gp:) < cr>
Criterios difícilmente alcanzables: Favorecer Pi ? Perjudicar Pj
71 Planificación de Procesos ( PCPU vs PE/S ) (Gp:) PCPU
(Gp:) PE/S
(Gp:) Periodos largos de CPU
(Gp:) Periodos cortos de CPU
? ¿Cómo reconocerlos? (Gp:) Abandona voluntariamente la UCP
72 Sistemas Batch No expulsores o expulsores con un quantum grande Reducen cambios de contexto y mejoran el rendimiento Por niveles, 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 Planificación de Procesos ( Políticas )
73 Planificación de Procesos ( Por niveles ) (Gp:) Planificación a medio plazo Memoria (Gp:) Planificación a corto plazo CPU (Gp:) CPU (Gp:) IT2 (Gp:) T2 (Gp:) T3 (Gp:) T5 (Gp:) T1, T2, T3, T4, T5, T6 (Gp:) S.O. (Gp:) Entrada al sistema
(Gp:) frecuencia alta
(Gp:) frecuencia baja
74 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 (Gp:) A
(Gp:) B
(Gp:) A (Gp:) D (Gp:) B (Gp:) C
(Gp:) D (Gp:) B (Gp:) C (Gp:) A (Gp:) E/S
Sencillo, pero ? Ausencia de política (Gp:) D (Gp:) C (Gp:) B (Gp:) A (Gp:) 4 4 4 8 (Gp:) D (Gp:) C (Gp:) B (Gp:) A (Gp:) 8 4 4 4
(Gp:) Tesp (Gp:) Tret
(Gp:) 9 (Gp:) 14
(Gp:) Tesp (Gp:) Tret
(Gp:) 6 (Gp:) 11
"Efecto convoy" (Gp:) {PE/S}n (Gp:) PUCP
(Gp:) PE/S (Gp:) {PE/S}n-1 (Gp:) PUCP (Gp:) E/S (Gp:) T >>
(Gp:) T <
75 Planificación de Procesos ( Efecto convoy ) PUCP = {10UCP + 2E/S}* PE/S = {1UCP + 2 E/S}* (Gp:) PUCP (Gp:) PE/S
CPU al 100%, pero tan sólo 30 unidades de tiempo en E/S CPU al 100% y además, 55 unidades de tiempo en E/S (Gp:) PUCP (Gp:) PE/S (Gp:) ??
76 Planificación de Procesos ( El más corto primero SJF ) (Gp:) Objetivo: Minimizar Tesp/ret
(Gp:) 8 (Gp:) 5 (Gp:) 4 (Gp:) 3
(Gp:) CPU
3 4 5 8 ¿Óptimo? (Gp:) ¿Dónde esperan los procesos?
(Gp:) CPU (Gp:) preparados
¿Aplicable SJF en planificación a largo y a corto plazo? (Gp:) ¿Más corto?
Tiempo total de CPU Lo declara el usuario Si engaña ? KILL (Gp:) ¿Más corto?
(Gp:) Sistemas interactivos
(Gp:) Contraejemplo (Gp:) 0 1 2 3 4 (Gp:) A(2) B(4) (Gp:) C(1) D(1) E(1)
77 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 0 1 2 3 4 5 6 7 A(2) B(4) C(1) D(1) E(1) ¿Tiempo medio de espera? Planificación de Procesos ( Tiempo restante menor SRTN )
78 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 (Gp:) La consume totalmente y se le expulsa (Gp:) Pi (Gp:) rodaja
(Gp:) La usa parcialmente y abandona voluntariamente la UCP (Gp:) Pi (Gp:) sleep, wait, exit
Política FIFO de gestión de la cola de preparados Dos cuestiones de diseño: ¿Cómo elegir el tamaño de la rodaja? ¿Cómo determinar el fin de rodaja? Ley del 80%
79 Planificación de Procesos (Round Robin) ¿Cómo elegir el tamaño de la rodaja? Sea Tcc = 5 mseg (mucho) Rodaja pequeña 20 mseg => Burocracia del 20% Rodaja grande 500 mseg => Burocracia del 1% (Gp:) UCP útil
(Gp:) Respuesta lenta a usuarios interactivos
(Gp:) ¿Degenera en FCFS?
(Gp:) Mejor interactividad
(Gp:) Ejemplo: P1, P2, P3 => 24, 3 y 3. Rodajas 4 vs 12 y Tcc = 0,5
P1 P2 P3 P1 (Gp:) P1 (Gp:) P1 (Gp:) P1 (Gp:) P1 (Gp:) 33,5
(Gp:) P1 (Gp:) P2 (Gp:) P3 (Gp:) P1 (Gp:) 31,5
Valores comunes: 20..50 mseg
80 Planificación de Procesos (Round Robin) ¿Cómo determinar el fin de rodaja? Una interrupción periódica (Gp:) P1
(Gp:) P2
(Gp:) P3
(Gp:) P4
(Gp:) sleep
(Gp:) ¿Somos justos con P3?
(Gp:) ¿viable?
F(int) en 68901 [1µseg..20mseg] Dar 2 rodajas Resetear interrupción Sumar ticks de una interrupción más frecuente (Gp:) P1 (Gp:) P2 (Gp:) sleep (Gp:) P3 (Gp:) P4
81 Planificación de Procesos (Prioridades) "Unos más importantes que otros": Cada Pi prioridad explícita (Gp:) 0 N N 0 (Gp:) mín (Gp:) máx
(Gp:) expulsora (Gp:) P3 (Gp:) P7 (Gp:) 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 (Gp:) Sencillo pero inanición
(Gp:) P3 (Gp:) P7 (Gp:) P1 (Gp:) P9
(Gp:) ¿ tiempo real ?
(Gp:) no expulsora (Gp:) P3 (Gp:) P7 (Gp:) P1
82 Planificación de Procesos (Prioridades dinámicas) Evitar la inanición: Disminuir la prioridad a medida que se usa la UCP Aumentar la prioridad si se está tiempo en preparados ¿ Favorece a los trabajos cortos ? (Gp:) PE/S vs PUCP
Favorece a los Pi ligados a E/S ¿Cuáles son PE/S? ¿Todo el tiempo será PE/S? (Gp:) PE/S aquellos que usen una parte menor de la rodaja de UCP
Ejemplo con rodajas de 100 mseg: P1 usa 2 mseg de UCP ? PE/S P2 usa 25 mseg de UCP ? PUCP (Gp:) Prio (P1) = 100/2 = 50 Prio (P2) = 100/25 = 4
¿Rango de prioridades [0..N]? (Gp:) Estáticas muy bajo ? 16 Dinámicas muy variable
83 Planificación de Procesos (Múltiples colas) "Mezcla de políticas": Cada Pi asociado a una cola de forma estática (Gp:) Prioridad (Gp:) 3 (Gp:) 2 (Gp:) 1 (Gp:) 0
(Gp:) FCFS
(Gp:) Round Robin
(Gp:) Quantum (Gp:) 4 (Gp:) 8 (Gp:) 16
Dos elecciones: Seleccionar cola Seleccionar proceso dentro de la cola (Gp:) ¿Expulsora?
84 Planificación de Procesos (Múltiples colas realimentadas) "Mezcla de políticas": Cada Pi asociado a una cola de forma dinámica Menos Cambios de Contexto (Gp:) Prioridad (Gp:) 4 (Gp:) 3 (Gp:) 2 (Gp:) 1 (Gp:) 0
(Gp:) 1 (Gp:) + Rodajas Variables
2 4 8 16 Rodajas para Pi ? 1, 2, 4, 8, 16 Favorecer selectivamente PE/S (Gp:) Prioridad (Gp:) 3 Terminal 2 E/S 1 Rodaja corta 0 Rodaja larga
Consumir rodajas: Bajar de prioridad
85 Planificación de Procesos (MINIX 3) (Gp:) /usr/src/kernel/proc.h
(Gp:) Pi
(Gp:) SI consumió su rodaja Nueva rodaja Prioridad++ ¡Menor! Encolar_Al_Final SINO Encolar_Al_Principio (Gp:) sched
(Gp:) Preparados (Gp:) MaxPrioridad (Gp:) MinPrioridad
(Gp:) RoundRobin
(Gp:) proc[log].p_nextready
86 Planificación de Procesos ( Pi más corto siguiente SPN ) (Gp:) CPU (Gp:) preparados (Gp:) ¿Más corto? (Gp:) ¿Más corto? (Gp:) SJF (Gp:) SPN
(Gp:) Tiempo de próxima posesión de UCP
? (Gp:) ¿Predicción? (?i) ?
?i+1 = F (ti, ?i) ?i+1 = ? ti + (1- ?) ?i y ? = 1/2 Predicción (Gp:) ?i ? (Gp:) ti ?
10 6 8 4 (Gp:) 6 (Gp:) 6 (Gp:) 6 (Gp:) 4 (Gp:) 5 (Gp:) 13 (Gp:) 9 (Gp:) 13 (Gp:) 11 (Gp:) 13 (Gp:) 12
87 Dado m eventos periódicos evento i ocurre en el periodo Pi y precisa Ci segundos El sistema es planificable si Hard real time vs Soft real time
Eventos: periódicos vs aperiódicos (Leer las secciones 7.4.2, 7.4.3 y 7.4.4) Planificación de Procesos ( Sistemas de Tiempo Real )
88 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
Planificación de Procesos ( Política vs Mecanismo ) pthread_attr_setschedpolicy(.) => FIFO, RR, OTHERS
89 Quantum por proceso de 50 mseg Cada thread ejecuta 5 mseg de ráfaga de CPU Planificación de Threads ( Espacio de usuario )
90 Planificación de Threads ( Espacio de kernel ) Quantum por proceso de 50 mseg Cada thread ejecuta 5 mseg de ráfaga de CPU
91 Sistemas multiprocesador (Gp:) µP1 (Gp:) µP2 (Gp:) µP3 (Gp:) µP4
Cada µP su cola (Gp:) Peligro de carga desequilibrada
(Gp:) µP1 (Gp:) µP2 (Gp:) µP3 (Gp:) µP4
¡ Ojo ! ? Spin Lock Planificar ? ¿Qué thread? ¿En qué núcleo? Tiempo compartido Threads independientes Cola única (Gp:) No escalable con aumento núcleos
(Gp:) Espera activa si FR ? Spin Lock
(Gp:) ¡Estoy en RC! ? Alarga rodaja
(Gp:) Problemática caches ? Afinidad
92 Sistemas multiprocesador Ordenando 128.000 claves "burbuja" en Intel Core 2 Quad Q6600 2,46GHz (Gp:) µP0 (Gp:) 4MB L2 (Gp:) µP1 (Gp:) µP2 (Gp:) 4MB L2 (Gp:) µP3
sched_setaffinity
93 Sistemas multiprocesador Espacio compartido Threads cooperantes Apropiarse {µP}n (Gp:) Núcleo ocioso cuando Pi.bloqueado
(Gp:) Sin multiprogramación ? ¡Menos burocracia!
(Gp:) Sin "n" núcleos libres no me ejecuto
(Gp:) Servidor Web con {threads} variable
94 Sistemas multiprocesador Planificar por pandillas Threads cooperantes Tiempo/Espacio (Gp:) Espacio compartido
(Gp:) Tiempo compartido
Página anterior | Volver al principio del trabajo | Página siguiente |