Sincronización de Procesos y Hilos en Sistemas Operativos: Módulos del Kernel, Cerrojos, Semáforos y Problemas Clásicos
Ejemplo de los nadadores que tienen barreras
TODO: ejemplo de los nadadores que tienen barreras y es completito.
Módulos para el kernel
- Los módulos se ubican en /lib/modules.
- Para ver los módulos cargados: lsmod.
- Código de un módulo: debe contener las funciones init_module y cleanup_module.
- Cargar el módulo: insmod.
- Descargar el módulo: rmmod.
- Dispositivos de caracteres (chrdev): para crear el archivo se asigna un major y un minor.
- Creación del archivo de dispositivo: mknod -m 666 (permisos) c (tipo de dispositivo: carácter).
Cerrojo (mutex)
Atributos: estado, cola y hilo_propietario.
- lock: si el estado está cerrado, añade el hilo a la cola, suspende el hilo y, al despertar, lo borra de la cola. Si el estado está abierto, cierra el cerrojo, asigna como propietario este hilo.
- unlock: si soy el propietario, abro el estado, pongo propietario = null; si la cola no está vacía, despierto un hilo.
Semáforo
Atributos: cola de procesos y contador.
- wait: decrementa el contador (contador--); si el contador es menor que 0, bloquea el proceso.
- signal: incrementa el contador (contador++); si hay procesos bloqueados, libera un proceso.
Variable de condición
Compuesta por una cola de espera y un mutex.
- wait: añade el hilo a la cola, libera el mutex, duerme el hilo y, al despertar, recupera el mutex.
- signal: si la cola no está vacía, despierta un hilo.
- broadcast: despierta a todos los hilos en espera.
Algoritmo de Peterson
while (turno && interesado[i]); // espero
// sección crítica
interesado[i] = false;
// fin secciónInstrucciones máquina
Test and Set (T&S)
while (tas(dirMem, 1)) {}
// sección crítica
*dirMem = 0;Swap / Exchange
tmp = 1;
while (tmp) {
xchg(dirM, tmp);
// sección crítica
*dirM = 0;
}LL/SC (Load-Linked / Store-Conditional)
while (1) {
while (ll(dirM));
if (sc(dirM, 1)) break;
// si no, otra vez al load-link
}
// sección crítica
*dirM = 0;Productor/consumidor con variables de condición
buffer[max_buff];
indProd = 0, indCons = 0;
mutex_t m;
cond_t event;
void productor() {
mutex_lock(&m);
while (n_elementos == max_buff) cond_wait(&event, &m);
cond_broadcast(&event);
mutex_unlock(&m);
...
}
void consumidor() {
mutex_lock(&m);
while (!n_elementos) cond_wait(&event, &m);
cond_broadcast(&event);
mutex_unlock(&m);
...
}Productor/consumidor con semáforos
void productor() {
int dato, i;
for (i = 0; i < N; i++) {
// producir dato
dato = producir_dato();
sem_wait(&huecos); // un hueco menos
buffer[prod] = dato;
prod = (prod + 1) % max_buff;
sem_post(&elementos); // un elemento más
}
thread_exit(0);
}
void consumidor() {
int dato, i;
for (i = 0; i < N; i++) {
sem_wait(&elementos); // un elemento menos
dato = buffer[cons];
cons = (cons + 1) % max_buff;
sem_post(&huecos); // un hueco más
consumir_dato(dato);
}
salir_hebra(0);
}Lectores/escritores con semáforos
void lector() {
while (1) {
sem_wait(&sem_lec);
n_lectores++;
if (n_lectores == 1) sem_wait(&cerrojo);
sem_post(&sem_lec);
// leer recurso
sem_wait(&sem_lec);
n_lectores--;
if (n_lectores == 0) sem_post(&cerrojo);
sem_post(&sem_lec);
}
}
void escritor() {
while (1) {
sem_wait(&cerrojo);
dato += 2; // modificamos recurso
sem_post(&cerrojo);
}
}