Paso de Mensajes Sistemas Operativos Mensajes permiten: Paso de Mensajes Sincronización de procesos Comunicación entre procesos Mario Medina (mariomedina@udec.cl) Aptos para: Sistemas distribuidos Sistemas multiprocesadores Sistemas monoprocesadores con memoria compartida Beware of bugs in the above code; I have only proved it correct, not tried it. Primitivas básicas Cuidado con errores en el código anterior; demostré que está correcto, pero no lo he probado. Donald E. Knuth send(dest, msg) Enviar mensaje msg a proceso destino dst receive(orig, msg) Recibir mensaje msg desde proceso origen orig Parámetros de implementación Tipo de sincronización Direccionamiento Formato de los mensajes (largo fijo, variable, etc.) Polı́tica de las colas (FIFO, prioridades, etc.) Sistemas Operativos, 2008-1 Sistemas Operativos, 2008-1 Sincronización de mensajes 1 Direccionamiento de Mensajes Mensajes send(dest, msg) Cómo especificar los procesos que envı́an y deben recibir Bloqueante Proceso se bloquea hasta que se recibe el mensaje No Bloqueante Proceso no se bloquea Direccionamiento Directo primitivas incluyen identificador unı́voco del proceso con el que se quiere comunicar Requiere conocer de antemano los procesos origen y destino Mensajes receive(orig, msg) Direccionamiento Implı́cito Identificador de proceso que recibirá mensaje incluı́do en mensaje recibido anteriormente Bloqueante Proceso se bloquea hasta que se llega un mensaje No Bloqueante Proceso no se bloquea send() bloqueante, receive() bloqueante (Rendez-Vous) • Combinación permite sincronización estricta entre varios procesos send() no bloqueante, receive() bloqueante • Combinación más común • Requiere de mensajes de respuesta para acusar recibo (ACK) Sistemas Operativos, 2008-1 2 Direccionamiento Indirecto Mensajes se envı́an a un buzón ó casilla (mailbox) Este esquema desacopla al emisor y al receptor Buzones pueden ser estáticos o dinámicos Quién es el propietario del buzón? • Proceso origen • Proceso destino • Sistema Sistemas Operativos, 2008-1 3 Exclusión Mutua con Mensajes send() no bloqueante S1 S1 Port R1 receive() bloqueante • • • R1 Port Sn (a) One to one S1 Mailbox (b) Many to one R1 S1 • • • • • • Rn Sn (c) One to many R1 • • • Mailbox Rn (d) Many to many Buzón mutex usado para asegurar exclusión mutua • Buzón inicialmente tiene un mensaje ◦ En este caso, contenido del mensaje es irrelevante • Proceso retira mensaje antes de entrar a sección crı́tica • Proceso devuelve mensaje al buzón al salir de sección crı́tica Exclusión Mutua while(true) { receive(mutex, msg); /* Seccion critica */ send(mutex, msg); } Buzón con mensajes actúa como un semáforo Sólo un proceso puede retirar el mensaje, y el resto se bloquea Figure 5.18 Indirect Process Communication Cuando el proceso retorna el mensaje al buzón • Se elige algún proceso bloqueado y éste retira el mensaje Sistemas Operativos, 2008-1 Productor/Consumidor usando Mensajes Productor/Consumidor con Buffer Finito usando Mensajes Requiere de un buffer (buzón) infinito Productor envı́a mensajes con datos al buzón Consumidor retira mensajes con datos desde el buzón • Si buzón está vacı́o, consumidor se bloquea en espera de mensajes Productor while(true) { msg = producir(); send(buzon, msg); } Consumidor while(true) { recv(buzon, msg); consumir(msg); } Qué pasa si capacidad del buzón es finita? Productor necesita saber si hay espacio en el buzón para los datos Sólo consumidor sabe cuántos datos ha retirado del buzón • Consumidor debe enviar esta información al productor Se requieren dos buzones! • consBuzon y prodBuzon • Se definen dos canales de comunicación unidireccional Sistemas Operativos, 2008-1 4 5 Productor transmite el dato a consumir en el mensaje msgProd • Productor agrega mensajes con datos a consBuzon • Consumidor remueve mensajes de consBuzon y envı́a mensajes vacı́os a prodBuzon ◦ Contenido de mensajes del consumidor es irrelevante ◦ Número de mensajes en prodBuzon indica cuántos datos el consumidor puede recibir ◦ Inicialmente, prodBuzon se llena con n mensajes vacı́os • Si prodBuzon está vacı́o, productor se bloquea • Si consBuzon está vacı́o, consumidor se bloquea Productor while(true) { recv(prodBuzon, msgProd); msgProd = producir(); send(consBuzon, msgProd); } Consumidor while(true) { recv(consBuzon, msgCons); consumir(msgCons); send(prodBuzon, NULL); } Para pensar: Dónde está la exclusión mutua? Sistemas Operativos, 2008-1 6 Solución via semáforos: lectores tienen prioridad Problema de los Lectores/Escritores Área de datos compartida Lectores sólo leen datos Escritores sólo escriben datos Solución debe cumplir con reglas • Cualquier número de lectores puede leer simultáneamente • Sólo un escritor puede escribir en un instante dado • Si un escritor está modificando datos, ningún lector puede leerlos Solución: Proteger área compartida con semáforos • Inconveniente: un proceso accesa datos a la vez • Lectores no modifican los datos ◦ Permitir acceso de lectores en paralelo Lectores tienen prioridad • Si un lector tiene acceso a los datos, otros lectores pueden hacerlo también • Peligro de inanición para los escritores Escritores tienen prioridad • Una vez que un escritor ha declarado su intención de escribir, nuevos procesos lectores no tienen acceso a datos Sistemas Operativos, 2008-1 7 Solución via semáforos: escritores tienen prioridad Semáforo writeSem controla exclusión mutua • Valor inicial: 1 Semáforo readSem inhibe las lecturas mientras haya al menos un escritor que acceda a los datos • Valor inicial: 1 Variable readCount cuenta a los lectores Variable writeCount cuenta a los escritores Semáforo readMutex protege variable readCount • Valor inicial: 1 Semáforo writeMutex protege variable writeCount • Valor inicial: 1 Semáforo z encola a procesos lectores que intentan leer cuando hay un proceso escritor activo • Valor inicial: 1 • Nuevos procesos escritores tienen prioridad • Procesos lectores deben esperar que todos los procesos escritores hayan terminado antes de proseguir • Primer lector se bloquea en semáforo readSem • Lectores siguientes se bloquean en semáforo z Sistemas Operativos, 2008-1 9 Semáforo writeSem controla exclusión mutua entre lectores y escritores (valor inicial: 1) Variable readCount cuenta a los lectores Semáforo x protege variable readCount • Controla exclusión mutua entre lectores Lector while (true) { wait(x); readCount++; if (readCount == 1) { wait(writeSem); } signal(x); ReadData(); wait(x); readCount−−; if (readCount == 0) { signal(writeSem); } signal(x); } Escritor while (true) { wait(writeSem); WriteData(); signal(writeSem); } Sistemas Operativos, 2008-1 8 Solución via semáforos: escritores tienen prioridad (2) Lector while (true) { wait(z); wait(readSem); wait(readMutex); readCount++; if (readCount == 1) { wait(writeSem); } signal(readMutex); signal(readSem); signal(z); ReadData(); wait(readMutex); readCount−−; if (readCount == 0) { signal(writeSem); } signal(readMutex); } Sistemas Operativos, 2008-1 Escritor while (true) { wait(writeMutex); writeCount++; if (writeCount == 1) { wait(readSem); } signal(writeMutex); wait(writeSem); WriteData(); signal(writeSem); wait(writeMutex); writeCount−−; if (writeCount == 0) { signal(readSem); } signal(writeMutex); } 10 Solución via paso de mensajes: escritores tienen prioridad Proceso controlador Controlador Tres tipos de procesos Lectores solicitan acceso de lectura vı́a mensaje a buzón readReq Escritores solicitan acceso de escritura vı́a mensaje a buzón writeReq Cada proceso reciben autorización de acceso en un buzón propio Identificados por readID y writeID, respectivamente Cada proceso indica fin de acceso mediante mensaje al buzón done Controlador da servicio a los mensajes de lectores y escritores Da prioridad a escritores sobre los lectores Asegura exclusión mutua entre escritores Asegura acceso paralelo de varios lectores Sistemas Operativos, 2008-1 11 Código de los procesos Lectores y Escritores Sistemas Operativos, 2008-1 12 Controlador while (true) { if (count > 0) { if (notEmpty(done)) { receive(done, msg); count++; } else if (notEmpty(writeReq)) { receive(writeReq, writeID); count = count - 100; } else if (notEmpty(readReq)) { receive(readReq, readID); count−−; send(buzon[readID], NULL); } } if (count == 0) { send(buzon[writeID], NULL); receive(done, msg); count = 100; } while(count < 0) { receive(done, msg); count++; } } Lector while (true) { msg = readID; send(readReq, msg); receive(buzon[readID], msg); ReadData(); msg = readID; send(done, msg); } Escritor while (true) { msg = writeID; send(writeReq, msg); receive(buzon[writeID], msg); WriteData(); msg = writeID; send(done, msg); } Sistemas Operativos, 2008-1 Variable count se inicializa a algún número grande • Tres casos • Si count > 0, no hay escritores esperando y puede o no haber lectores activos ◦ Atender todos los mensajes en buzón done ◦ Luego, atender a los escritores que solicitan acceso ◦ Luego, atender a los lectores que solicitan acceso • Si count == 0 ◦ Un escritor ha solicitado acceso a los datos y no hay lectores activos ◦ Enviar mensaje NULL a buzón del escritor ◦ Esperar su mensaje done ◦ hacer count = 100 para permitir acceso de futuros lectores • Si count < 0 ◦ Un escritor ha solicitado acceso a los datos y hay lectores activos ◦ Procesar sólo mensajes de lectores en buzón done count < 0 bloquea futuros lectores hasta que count sea 0 13 Sistemas Operativos, 2008-1 14 Problema de la barberı́a Una barberı́a tiene • 3 barberos • 3 sillas de barbero • 1 caja registradora • Un sofá para 4 personas • Una sala de espera para el resto de los clientes Barber chairs Medidas contra incendios limitan el número de personas en la barberı́a a 20 Cashier Entrance Un cliente no entrará a la barberı́a si la capacidad está copada Una vez dentro, se sienta en el sofá si está libre, o queda de pie Un barbero libre atiende al cliente que lleva más tiempo en el sofá y el cliente que lleva más tiempo de pie se sienta en el sofá • Polı́tica FIFO impide inanición Standing room area Al terminar el corte, cualquier barbero puede aceptar el pago • Sólo un cliente paga a la vez Sistemas Operativos, 2008-1 Figure 5.18 The Barbershop Cliente de la barberı́a Semáforo capacidad regula el número de clientes en la barberı́a • Valor inicial = 20 Semáforo sofá: el cliente espera por el sofá Semáforo sillaBarbero: el cliente espera por una silla libre Semáforo clienteListo: barbero espera que cliente se siente Semáforo terminado: el barbero terminó su labor Semáforo dejarSilla: barbero espera que el cliente desocupe la silla Semáforo pago: el cajero espera por el pago Semáforo recibo: el cliente espera por el recibo Sistemas Operativos, 2008-1 Sofa 15 Solución usando Semáforos Barbero while (true) { wait(clienteListo); wait(coord); CortarPelo(); signal(coord); signal(terminado); wait(dejarSilla); signal(sillaBarbero); } Exit Cajero while (true) { wait(pago); wait(coord); RecibirPago(); signal(coord); signal(recibo); } Cliente while (true) { wait(capacidad); entrarBarberı́a(); wait(sofa); sentarseSofa(); wait(sillaBarbero); levantarseSofa(); signal(sofa); sentarseSillaBarbero(); signal(clienteListo); wait(terminado); levantarseSillaBarbero(); signal(dejarSilla); pagar(); signal(pago); wait(recibo); salirBarberia(); signal(capacidad); } Solución mostrada usa semáforos como señales Ojo: solución presentada no es perfecta! 16 Sistemas Operativos, 2008-1 17