Mensajes. (versión preliminar)

Documentos relacionados
Monitores. Implementación de un Buffer con monitores

Receta general para resolver problemas de sincronización con semáforos

Sistemas Operativos Práctica 4

Memoria compartida y semáforos r/w. La página del manual que podría servir para describir estas funciones es la siguiente:

Concurrencia: deberes. Concurrencia: Exclusión Mutua y Sincronización. Concurrencia. Dificultades con la Concurrencia

Árboles. Cursos Propedéuticos Dr. René Cumplido M. en C. Luis Rodríguez Flores

Concurrencia: Exclusión mutua y Sincronización

Concurrencia. Primitivas IPC con bloqueo

Object 1. Threads en Java

un programa concurrente

Ejemplos de conversión de reales a enteros

MONITORES EN JAVA. Antonio Tomeu Control de la Concurrencia en Java: API Estándar

RESUMEN DE CONCEPTOS BASICOS DE PROGRAMACION JAVA

En cualquier caso, tampoco es demasiado importante el significado de la "B", si es que lo tiene, lo interesante realmente es el algoritmo.

Introducción a la programación orientada a objetos

Sistemas Operativos. Características de la Multiprogramación. Interacción entre Procesos. Características de la Multiprogramación

Concurrencia entre Procesos.

SISTEMAS OPERATIVOS AVANZADOS

4. Programación Paralela

Examen de Fundamentos de sistemas operativos

Examen de Fundamentos de sistemas distribuidos

Threads. La plataforma JAVA soporta programas multhreading a través del lenguaje, de librerías y del sistema de ejecución. Dos.

Información sobre la configuración de una aplicación para transmitir datos ASCII por puerto serie, con pantallas terminales Magelis.

Tecnólogo Informático- Estructuras de Datos y Algoritmos- 2009

FUNDAMENTOS DE PROGRAMACIÓN. SEPTIEMBRE 2005

PROGRAMACIÓN EN JAVA

Hilos en Java. Crear un Hilo. Detener un hilo. Fuente:

Listas, Pilas, Colas y Punteros. Semana 3

CDI Exclusión mutua a nivel alto. conceptos

LENGUAJE. Tema 1 - Introducción

Mensajes. Interbloqueo

Benemérita Universidad Autónoma del Estado de Puebla

PROGRAMACIÓN CONCURRENTE. Tema 5 Monitores

Pontificia Universidad Católica de Chile Escuela de Ingeniería Departamento de Ciencia de la Computación

3.1 INGENIERIA DE SOFTWARE ORIENTADO A OBJETOS OOSE (IVAR JACOBSON)

Organización de Computadoras

En términos generales, un foro es un espacio de debate donde pueden expresarse ideas o comentarios sobre uno o varios temas.

Examen Febrero de 2012

TEMA 5. CONTROL DE FLUJO DEL PROGRAMA. Sentencia Instrucción Expresión Operadores + Operandos Sintaxis: Sentencia ;

Modulo 1 El lenguaje Java

Escuela Politécnica Superior de Ingeniería Departamento de Ingeniería Informática

Tema 4. Gestión de entrada/salida

Titulación: Ingeniero Técnico en Informática de Gestión Curso: 2º

Objetivos de la práctica: - Practicar uso de ficheros: abrir, cerrar y tratamiento de información contenida en el fichero.

Prof. Dr. Paul Bustamante

SALIDAS ANALÓGICAS. Adquisición de datos y acondicionamiento de la señal Tema 6

ATEL ASESORES C.A IP Multimedia Subsystem Prof. Diógenes Marcano

Arquitectura de sistema de alta disponibilidad

Resumen del trabajo sobre DNSSEC

Ingeniería Superior de Informática. Curso 3º. Sistemas Operativos. Examen Final. TEORÍA. 31 de Enero de 2005

En el presente capítulo se describe la programación del instrumento virtual y cómo

MGX CANAL DE SOPORTE Y ASISTENCIA

Solución al Examen de Prácticas de Programación (Ingeniería Informática)

GESTIÓN DE EXCEPCIONES EN JAVA. CAPTURA CON BLOQUES TRY CATCH Y FINALLY. EJEMPLOS RESUELTOS. (CU00927C)

Se ha desarrollado el siguiente programa principal. Se pide: arquitectura que permita una fácil extensión

MANUAL PARA GESTIÓN DE INCIDENCIAS INFORMÁTICAS

DEFINICION. Ing. M.Sc. Fulbia Torres Asignatura: Estructuras de Datos Barquisimeto 2006

Implementación de monitores POSIX

El problema de los Filósofos

! Una variable declarada con final no puede volver a ser reinicializada. numero = 2;! ! Para definir constantes

2. Estructura de un programa en Java

8. Sentencia return y métodos

1 HILOS (THREADS) EN JAVA

Creación y administración de grupos de dominio

Transacciones y bloqueos en SQL-Server

Práctica de laboratorio Uso de ping y tracert desde una estación de trabajo

MODELO: 301 RESPALDO DE TARJETA SIM

PRUEBAS DE SOFTWARE TECNICAS DE PRUEBA DE SOFTWARE

Prof. Dr. Paul Bustamante

TPV Táctil. Configuración y Uso. Rev /01/09

Examen Junio- Grupo A Lunes 17 de Junio - Programación en C++ Pág. 1

DISCOS RAID. Se considera que todos los discos físicos tienen la misma capacidad, y de no ser así, en el que sea mayor se desperdicia la diferencia.

Sistema de Soporte a Clientes

Recargas de Celulares

Resolver triángulos en Visual Basic. Parte 3/3

PROCEDIMIENTO PARA INGRESAR AL CORREO DE REDP POR MEDIO DEL OWA (OUTLOOK WEB ACCESS) El procedimiento ingresar al correo de RedP es el siguiente:

Instrumentación Virtual con LabVIEW

Figura 1: Símbolo lógico de un flip-flop SR

SIMM: TEORÍA DE LOS S.O. I.E.S. JUAN DE LA CIERVA CURSO 2007/2008

La nueva criba de Eratóstenes Efraín Soto Apolinar 1 F.I.M.E. U.A.N.L. San Nicolás, N.L. México. efrain@yalma.fime.uanl.mx

Apuestas de lotería on-line mediante teléfonos móviles

3. Número inicial y número final de mensajes mostrados en la página actual.

DCU Diagramas de casos de uso

Tema 3: Herencia en C++ Programación Orientada a Objetos Curso 2008/2009 Begoña Moros Valle

Instrucciones para Integración con PayPal

TUTORIAL DE PHP. M. en C. Erika Vilches. Parte 2.


Windows Server 2012: Zonas DNS

Java: Programación Multithread

El control de la tesorería consiste en gestionar desde la aplicación los cobros y pagos generados a partir de las facturas de venta y de compra.

Manual de NVU Capítulo 4: Los enlaces

PUESTA EN MARCHA PROGRAMA GESTION DE OPTICAS. Junio

Sistemas Operativos Temas 4, 5 y 6. Jorge García Duque Despacho: B-202 Tutorías: Lunes 16:00-18:00 y Martes 16:00-20:00

Prof. Dr. Paul Bustamante

Medias Móviles: Señales para invertir en la Bolsa

Práctica 3 Verificación de Especificaciones Z con Z/EVES

Mi primer proyecto en Dev-C++

APRENDE A CREAR UNA PÁGINA WEB CON HTML

LINEAMIENTOS PARA LA CANCELACIÓN TOTAL DE SISTEMAS DE DATOS PERSONALES DEL INSTITUTO ELECTORAL DEL ESTADO DE MÉXICO CAPÍTULO I DISPOSICIONES GENERALES

Transcripción:

Mensajes (versión preliminar) Ejemplo: productor/consumidor con buffer de tamaño 0 void produce(item *p_it); void consume(item *p_it); int nmain() { ntask cons= nemittask(consproc); ntask prod= nemittask(prodproc, cons); nwaittask(cons); int prodproc(ntask dest) { Item it; produce(&it); nsend(dest, &it); int consproc() { Item it= *(Item*)nReceive(&t, -1); nreply(t, 0); /* se puede porque el item quedo almacenado localmente */ consume(&it); Cuidado: esta implementación del consumidor sería incorrecta: int consproc() { Item *p_it= (Item*)nReceive(&t, -1); nreply(t, 0); /* incorrecto! el productor podría destruir *pit */ consume(p_it); El problema está en que el puntero pit apunta hacia la variable it en el productor. Al responder el mensaje con nreply, el nsend en el productor se desbloquea y termina el bloque de la iteración. Con ello se destruye la variable it. Por lo tanto, cuando el consumidor usa *p_it, la variable a la que apunta pudo haber sido destruida. Entonces por qué no responder el mensaje después de consume? De esta forma, el consumidor quedaría como: int consproc() {

Item *p_it= (Item*)nReceive(&t, -1); consume(p_it); nreply(t, 0); La implementación sería correcta, pero no habrá paralelismo entre productor y consumidor. Cuando el productor envía el ítem al consumidor, se quedaría bloqueado en el nsend hasta que se haya consumido el ítem, y no podría producir al mismo tiempo que se consume. Entonces producir y consumir ocurrirían secuencialmente y se crearía inútilmente un thread para el consumidor. Buffer de 1 ítem Para implementar un buffer de 1 ítemes se crea una tarea intermedia que lo único que hace es recibir un ítem, almacenarlo localmente y luego reenviarlo al consumidor: int bufproc(ntask dest) { Item it= *(Item*)nReceive(&t, -1); nreply(t, 0); /* se puede porque el item quedo almacenado localmente */ nsend(dest, &it); El nmain se cambia por: int nmain() { ntask cons= nemittask(consproc); ntask buf= nemittask(bufproc, cons); ntask prod= nemittask(prodproc, buf); nwaittask(cons); /* Nunca termina: solo para evitar que nmain termine */ Ejercicio: cambie solo nmain para implementar un buffer de 2 ítemes. Equivalencia entre herramientas de sincronización Las tres herramientas de sincronización vistas en el curso (semáforos, monitores y mensajes) son equivalentes porque cualquier problema que se resuelva con una de ellas se puede resolver con cualquiera de las otras 2. Esto es trivialmente cierto porque cualquier herramienta de sincronización se puede implementar a partir de otra herramienta. Para probar esto mostraremos que (i) los monitores se pueden implementar a partir de semáforos, (ii) los semáforos se pueden implementar a partir de mensajes, y (iii) los mensajes se pueden implementar a partir de monitores. Monitores a partir de semáforos typedef struct node { nsem wait; struct node *next; Node; nsem mutex; Node *head;

Monitor; Monitor *makemonitor() { Monitor *mon= (Monitor*)nMalloc(sizeof(*m)); mon->mutex= nmakesem(1); mon->head= NULL; return mon; void monenter(monitor *mon) { nsemwait(mon->mutex); void monexit(monitor *mon) { nsemsignal(mon->mutex); void monwait(monitor *mon) { Node node; node.wait= nmakesem(0); node.next= mon->head; mon->head= &node; nsemsignal(mon->mutex); nsemwait(node.wait); /* se bloquea a la espera del notify */ ndestroysem(node.wait); nsemwait(mon->mutex); /* se bloquea a la espera del monitor */ void monnotifyall(monitor *mon) { Node *node; for (node= mon->head; node!=null; node= node->next) nsignalsem(node->wait); mon->head= NULL; Semáforos a partir de mensajes ntask qtask, server; Sem; typedef enum {SEMWAIT, SEMSIGNAL, SEMDESTROY SemOp; SemOp op; ntask emitter; Req; int semqueueproc(), semserverproc(int ini_tickets); Sem *makesem(int ini_tickets) { Sem *s= (Sem*)nMalloc(sizeof(*s)); s->server= nemittask(semserverproc, ini_tickets); s->qtask= nemittask(semqueueproc, s->server); return s; void destroysem(sem *s) {

Req req= {SEMDESTROY, ncurrenttask(); nsend(s->qtask, &req); nwaittask(s->server); nwaittask(s->qtask); void semwait(sem *s) { Req req= {SEMWAIT, ncurrenttask(); nsend(s->qtask, &op); void semsignal(sem *s) { Req req= {SEMSIGNAL, ncurrenttask(); nsend(s->server, &op); int semqueueproc(ntask server) { int finish= FALSE; do { Req *req= (Req*)nReceive(NULL, -1); if (req->op==semdestroy) finish= TRUE; nsend(server, req); while (!finish); return 0; int semserverproc(int tickets) { int finish= FALSE; do { Req *req= (Req*)nReceive(&t, -1); if (req->op==semdestroy) finish= TRUE; else if (req->op==semsignal) tickets++; else if (req->op==semwait) { if (tickets>0) tickets--; else { ntask signaltask; Req *sigrec= (Req*)nReceive(&signaltask, -1); if (sigrec!=semsignal) nfatalerror( semserverproc, se esperaba un SEMSIGNAL\n ); nreply(signaltask, 0); nreply(req->emitter, 0); nreply(t, 0); while (!finish); return 0; En este código, la tarea qtask hace las veces de cola de solicitudes de tickets. En efecto, observe en el código del servidor que cuando llega una solicitud de ticket (SEMWAIT), el servidor se queda esperando solo una notificación de depósito de ticket (SEMSIGNAL) y no se pone en el caso de que llegue otra solicitud de ticket. Esto se puede hacer porque al no responder el mensaje req proveniente de qtask, esa tarea no puede reenviar un nuevo mensaje, y cualquier solicitud de ticket tiene que pasar por qtask. La pregunta entonces es qué pasa con esas nuevas solicitudes de ticket? En realidad quedan encoladas en la cola de mensajes de qtask y serán procesados uno a uno a medida que qtask pueda recibirlos.

En este caso no es muy difícil escribir una versión que no use qtask. Todas las solicitudes de ticket deberán ser recibidas directamente por el servidor. Si no hay tickets disponibles esas solicitudes se deben encolar explícitamente en alguna estructura de datos. Haga el ejercicio usando el tipo FifoQueue incluido en nsystem. Mensajes a partir de monitores Ejercicio propuesto. Lectores/escritores con mensajes typedef enum { ENTERREAD, EXITREAD, ENTERWRITE, EXITWRITE RWOp; RWOp op; ntask emitter; Req; static ntask qtask; /* = nemittask(queueproc); */ static server; /* = nemittask(serverproc); */ static void sendop(op op, ntask t) { Req req= { Op, ncurrenttask() ; nsend(t, &req); void enterread() { sendop(enterread, qtask); void exitread() { sendop(exitread, server); void enterwrite() { sendop(enterwrite, qtask); void exitwrite() { sendop(exitread, server); static int queueproc() { Req *req= (Req)nReceive(NULL, -1); nsend(server, req); static int serverproc() { int readers= 0; ntask aux; /* Se autorizan lecturas hasta que llegue una solicitud de escritura */ Req *req= (Req*)nReceive(NULL, -1); /* Estado WAIT */ while (req->op!=enterwrite) { if (req->op==exitread) readers--; else { /* req->op==enterread */ readers++; nreply(req->emitter, 0); /* se autoriza una lectura */ nreply(qtask, 0); req= (Req*)nReceive(NULL, -1); /* Estado READ1 */ /* la escritura no ha sido autorizada aún */ while (readers>0) { /* se espera a que salgan los lectores */ nreceive(&aux, -1); /* Estado READ2: tiene que llegar un EXITREAD */ nreply(aux, 0); readers--; nreply(req->emitter, 0); /* se autoriza la escritura */ nreceive(&aux, -1); /* Estado WRITE: tiene que llegar un EXITWRITE */

nreply(aux, 0); Aquí nuevamente qtask hace las veces de cola de solicitudes de entrada. Haga el ejercicio de no usar qtask y manejar explícitamente una cola de solicitudes de entrada en el servidor y va a ver que resulta bastante más complicado que la versión de más arriba. Ejercicio: buffer de tamaño N Usando una metodología similar a la anterior programe un buffer de tamaño N para el problema del productor/consumidor. Use 2 procesos queue : uno para los get y el segundo para los put. Haga el diagrama de estados para el servidor.