SISTEMAS OPERATIVOS I. CURSO 2010/11. PRÁCTICA 2: Problema de los Productores/Consumidores (concurrencia de procesos)

Documentos relacionados
Sistemas Operativos I. Enxeñería Informática. Curso 2007/08. Práctica 2: Concurrencia de procesos: Productores/Consumidores.

Sistemas Operativos: Programación de Sistemas. Curso Oscar Déniz Suárez Alexis Quesada Arencibia Francisco J.

Prácticas de Sistemas operativos

Sistemas Operativos Ingeniería de telecomunicaciones Sesión 3: Concurrencia

Comunicación entre Procesos

Memoria Compartida. Llave de acceso. Segmento Compartido. estructura definida en A. estructura definida en B. Proceso B. Proceso A

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

Prácticas de Sistemas operativos

IPC SYSTEM V. Técnicas Digitales III Ing. Gustavo Nudelman Universidad Tecnológica Nacional - Facultad Regional Buenos Aires

Funciones POSIX III Funciones POSIX III. No Nombrados Nombrados. sem_open sem_open. sem_close sem_close. sem_unlink sem_unlink

Sincronización de Threads

Sistemas operativos. Hasta ahora hemos visto. Relación programa-sistema operativo Gestión de memoria

MC Hilda Castillo Zacatelco PROCESOS

Prácticas de Sistemas operativos

Práctica 2. Teoría. Memoria Compartida y Semáforos

Procesos e hilos: cálculo de

Biblioteca de sistema

PARTE II PROGRAMACION CON THREADS EN C

Procesos e Hilos en C

1. Procesos vs Hilos 2. Cuando se ejecutan los procesos 3. Fork 4. Clone 5. Cómo se ejucuta el fork? 6. do_fork() 7. copy_process 8.

Tema 6: Memoria dinámica

Prácticas de Sistemas Operativos

Concurrencia. Primitivas IPC con bloqueo

Algoritmos y Estructuras de Datos Ingeniería en Informática, Curso 2º SEMINARIO DE C++ Sesión 2

Práctica 1. Presentación de la práctica continua: Implementación de un intérprete de comandos.

Dobles: Es el caso de la instrucción if-else (punto 1.2).

Lenguaje C, tercer bloque: Funciones

Concurrencia, exclusión mutua y sincronización. Capítulo 5 HungriaBerbesi

Estados de un proceso

Mecanismos IPC System V

Punteros y Memoria Dinámica I

Concurrencia Monitores. Guillermo Román Díez

Análisis y escritura de las estructuras de control

SOLUCIONES. DURACIÓN: Dispone de 100 minutos para realizar el examen. SOLUCIÓN Esta es una posible solución al ejercicio planteado, escrita en C.

Nombre alumno: Ventajas: Inconvenientes:

Guía básica de programación en C++ estructurado. Manejo básico de la parte estructurada de C++

Sistemas operativos. Comunicación y sincronización de procesos

1. Interfaz de llamadas a la librería de fluxes

Sistemas operativos: una visión aplicada. Capítulo 5 Comunicación y sincronización de procesos

Ejercicios sobre tuberías

Memoria Compartida. Por: Samuel Díaz Cabrera

Ejercicios de Hilos. Índice

FLEX: A FAST LEXICAL ANALYZER GENERATOR

Tipos de Datos Recursivos

Repaso Lenguaje C Área de Servicios Programación (Ing. Elect. y Prof. Tec.), Programación I (TUG y TUR) y Electrónica programable (TUE)

Cursosindustriales. Curso de C / C++ Por Deimos_hack

Prácticas de Sistemas Operativos

SOLUCIONES. DURACIÓN: Dispone de 120 minutos para realizar el examen.

Examen Teórico (1/3 de la nota final)

Primer parcial de teoría 2013_2014_Q1

SOLUCION EXAMEN junio 2006

Sistemas Operativos Practica 1: procesos y concurrencia.

Manipulación de archivos estructurados

Tipos Recursivos de Datos

Prácticas de Sistemas Operativos

Programación. Test Autoevaluación Tema 6

GENERACIÓN DE EXÁMENES TIPO TEST

Escuela Politécnica Superior de Elche

EXAMENES RESUELTOS DE PROGRAMACION I

Definición de estructuras. Estructuras, uniones y enumeraciones. Declaración. Definición y declaración. (struct, union y enum)

Los semáforos en Unix

Todo programa en 'C' consta de una o más funciones, una de las cuales se llama main.

Sistemas Operativos. Procesos

PROBLEMA 1. Rellena el hueco 1 (línea 23). Realiza la reserva de memoria para almacenar los n puntos.

Laboratorio 2010 Principios de Programación

Escuela Politécnica Superior de Elche

Práctica 3. Paso de parámetros entre subrutinas. 3. Consideraciones sobre el paso de parámetros

Prácticas de Periféricos Interfaces y Buses

La secuencia de referencias a páginas para el proceso B es:

UNIDAD 8 Tipos de datos dinámicos: Punteros Asignación dinámica de memoria. Uso de punteros. Inicialización y asignación de punteros.

Unidad 1: Gestión de Procesos

Programación Concurrente Recopilación de teoría referente a la materia

PROGRAMACIÓN ORIENTADA A OBJETOS

APUNTADORES. Un apuntador es un objeto que apunta a otro objeto. Es decir, una variable cuyo valor es la dirección de memoria de otra variable.

Sistemas Operativos: Programación de Sistemas. Curso Oscar Déniz Suárez Alexis Quesada Arencibia Francisco J.

Introducción a Funciones

Primitivas de Sincronización

Sentencias iterativas

Operaciones de E/S en ANSI C

TEMA 7: Ficheros. TEMA 7: Ficheros Concepto de fichero

Práctica 4 Concurrencia en Java

Relación de prácticas de la asignatura METODOLOGÍA DE LA PROGRAMACIÓN Segundo Cuatrimestre Curso º Grado en Informática

Sincronización de procesos

Arquitecturas cliente/servidor

Sentencias de salto: break, continue, goto Sentencia de Salto: break

Departamento de Electrónica

Segundo control de teoría

FLEX: A FAST LEXICAL ANALYZER GENERATOR

BUCLES EN LENGUAJE C (ESTRUCTURA DE REPETICIÓN) CONDICIÓN, CONTADOR. EJEMPLOS. (CU00533F)

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

Programación Orientada a Objetos en C++

Programación 2 Curso 2017/2018. Práctica 0 Conceptos básicos

2.2 Nombres, Ligado y Ámbito

Transcripción:

SISTEMAS OPERATIVOS I. CURSO 2010/11 PRÁCTICA 2: Problema de los Productores/Consumidores (concurrencia de procesos) INTRODUCCIÓN: En esta práctica se tratará de resolver el problema de los productores/consumidores utilizando semáforos como medio de sincronización y utilizando memoria compartida en los elementos comunes a los distintos procesos. Cada productor escribirá por pantalla el instante en el que ha introducido un ítem en el búffer, el ítem introducido, y el contenido de dicho búffer. Asimismo, cada consumidor indicará el instante en el que obtiene un ítem del búffer compartido, el ítem obtenido, y el estado del búffer. Para la creación del búffer compartido, se utilizarán las funciones IPC para el manejo de memoria compartida (shmget, shmat, shmdt, shmctl, ). Para el manejo de semáforos, se deben utilizar, entre otras, las funciones: semget, semop y semctl. DESCRIPCIÓN GENERAL: La práctica consistirá en la creación de 4 programas: Inicializa.c: Crea los semáforos necesarios para la sincronización de productores y consumidores. Además crea el búffer en el que éstos añadirán o extraerán items. El tamaño del búffer vendrá indicado por el parámetro items. Por defecto se asumirá que el búffer tiene capacidad para 15 items (cada ítem es un carácter). En ningún caso, el tamaño del búffer podrá exceder el valor indicado por una constante MAX_ITEMS. Sintaxis: $inicializa items 15 Productor.c: Crea p procesos productores (parámetro -p). Cada proceso creado simula el funcionamiento de un productor, produciendo items (1 de cada vez) y añadiéndolos al búffer compartido. Un parámetro times indica el número de elementos que cada productor añadirá al búffer. Sintaxis: $productor p 3 times 30 Consumidor.c: Crea c procesos consumidores (parámetro -c). Cada proceso extrae items del búffer (1 de cada vez) y muestra su contenido. Un parámetro times indica el número de elementos que cada consumidor quitará del búffer. Sintaxis: $consumidor -c 7 times 30 Finaliza.c: Una vez que todos los productores y consumidores hayan finalizado su trabajo, se encarga de liberar todos los recursos utilizados (creados por inicializa.c ). Esto es, los semáforos creados, y el búffer compartido. Sintaxis: $finaliza PRODUCTORES/CONSUMIDORES: Los programas productor.c y consumidor.c se encargarán respectivamente de crear p procesos productores y c procesos consumidores. Para la creación de un número concreto de productores o consumidores, puede usarse la función fork(), como se muestra a continuación: main() { pid_t pid; int i; int np=10; //número de procesos a crear. for (i=0;i<np;i++) { pid=fork(); if (pid == 0) break; //un hijo printf( \n el padre del proceso %d es %d,getpid(),getppid()); Nota: El proceso padre no se convertirá en un productor/consumidor, sino que esperará a que cada hijo termine y mostrará su status. Véase man 2 wait para más información.

Cada proceso productor o consumidor, en lugar de un bucle infinito, se ejecuta N veces (en función del parámetro times) ejecutando el código asociado a un productor o consumidor respectivamente. Cada vez que el productor quiera producir un ítem, obtendrá un carácter del siguiente modo: el primer productor siempre dará lugar a una A, el segundo a una B, el tercero a una C, y así sucesivamente (se puede asumir que no habrá más de 25 productores distintos). Esto es, si hay 3 productores, el 1º escribirá siempre A s, el 2º escribirá B s y el 3º C s. Una vez que cada proceso accede a la sección crítica, las funciones anhadiritem() y obteneritem() dejan al productor/consumidor en espera un tiempo aleatorio entre 1 y 5 segundos (sleep). Además, se imprime la hora a la que empieza y termina de producir o consumir el correspondiente proceso. También se muestra el estado del búffer (número de items que contiene actualmente y los distintos items). Todas las salidas de información a pantalla se realizarán mediante la llamada al sistema write. char produceitem(int id_proc) {.. void anhadiritem(int id_proc, char item) { char mensaje [MAXCADENA]; time_t t; pid_t p; p=getpid(); t=time(null); sprintf (mensaje,"productor %d (%u): Comienzo anhadir item %c a las %s",id_proc,p,item,ctime(&t)); write (STDOUT_FILENO,mensaje,strlen(mensaje)); /*esperar tiempo aleatorio entre 1 y 5 segundos*/ anhadecola(item); mostrarbuffer(); //añade el item producido al búffer compartido sprintf (mensaje,"productor %d (%u): termino de ahadir %c a las %s",id_proc,p,item,ctime(&t)); write (STDOUT_FILENO,mensaje,strlen(mensaje)); BÚFFER COMPARTIDO: COLA CIRCULAR. El búffer que productores y consumidores comparten y donde se almacenan los diferentes items, se implementará como una cola circular. Struct tcolachar { char items[max_items]; //vector de longitud indicada en inicializa.c int maxnum, num, ppio, final; Typedef struct tcolachar tbuffer El número máximo de items que caben en el búffer (maxnum) se le indica al programa inicializa ; nótese que ha de cumplirse que maxnum <=MAX_ITEMS. El valor num, indica el número de elementos que actualmente están almacenados en la cola. Los valores ppio y final indican el principio y final de la cola; al ser una cola circular, al incrementar ppio y final de debe hacer posteriormente una operación de módulo con maxnum (ppio = (ppio +1) % maxnum). Puesto que queremos que el búffer (la cola de items) sea compartido por todos los procesos consumidores y productores, no es posible declararlo simplemente como: tbuffer buffer; ya que esto daría lugar a que cada proceso tuviese su propio búffer (una variable de tipo tbuffer llamada buffer), pero no sería compartida entre todos ellos. Esto haría, p ej, que los procesos consumidores no podrían ver los items generados por los productores.

Para poder compartir el búffer, usaremos las funciones de la librería IPC para manejo de memoria compartida shmget, shmat, shmdt, shmctl del siguiente modo: 1. El proceso padre crea un área de memoria compartida con tamaño suficiente para almacenar el búffer (sizeof(tbuffer)), usando la llamada shmget(). Shmget devuelve un número (shmid) que será usado como identificador de la zona de memoria compartida que se ha creado. A la función shmget() debe pasársele una clave (key), que puede obtenerse mediante la función ftok(). key_t key = ftok( /tmp, B ); shmid = shmget(key,..); 2. Usando el identificador que devuelve shmget, cada proceso podrá obtener un puntero a la zona de memoria compartida (el búffer), y a través de dicho puntero acceder a dicho búffer para añadir o quitar items. tbuffer *pbuffer; pbuffer=(tbuffer *) shmat(shmid,0,0); 3. A partir de ahí, cada proceso podrá usar pbuffer como si fuese un puntero a tbuffer normal, pero que se comporta ahora como una estructura compartida. 4. Al finalizar cada proceso productor o consumidor, se desasigna el puntero pbuffer usando shmdt. 5. Por último, el programa finaliza.c destruye el área de memoria compartida usando shmctl. UTILIZACIÓN DE SEMÁFOROS. La implementación propuesta requiere el uso de 3 semáforos: vacío, lleno y búffer. La creación de semáforos se hará mediante la llamada al sistema semget(). Se pueden implementar las operaciones básicas para la manipulación de cada semáforo haciendo uso de la llamadas semop() y semctl(). Finalmente la llamada semctl() permitirá liberar dicho recurso. Más concretamente: - semget: Permite obtener un grupo de k semáforos que será identificado por un identificador semid. - semop: Opera sobre uno de los semáforos (i) del grupo obtenido con semget (grupo identificado por semid), y permite entre otras, hacer las operaciones P y V sobre alguno de los semáforos del grupo. - semctl: se encarga de liberar un grupo de semáforos identificado por semid cuando ejecuta el comando IPC_RMID. También permite establecer un valor a un semáforo determinado, cuando a través de semctl se ejecuta el comando SETVAL. NOTA: Al igual que shmget(), semget() recibe como parámetro un valor key_t key, que puede obtenerse previamente con la función ftok(). Deberemos asegurarnos de que la clave que devuelva ftok sea distinta que la obtenida para crear el búffer_compartido, y la misma para todos los procesos que han de compartir el mismo semáforo. Básicamente semget() permite obtener un grupo de k semáforos. En nuestro caso será necesario simplemente disponer de un grupo de k=3 semáforos (vacío, lleno y búffer). Como cada uno de estos semáforos ha de ser accedido utilizando un número {0,1,2, se aconseja definir constantes para identificar cada semáforo de modo que: - el semáforo vacío se identificará con un 0. - el semáforo lleno se identificará con un 1. - el semáforo mutex se identificará con un 2.

MÁS INFORMACIÓN Y COMANDOS DE INTERÉS. Véase manual en línea para las funciones comentadas. Ipcs e ipcrm para ver y eliminar recursos compartidos (semáforos o segmentos de memoria compartida) desde la línea de comandos. FECHA LÍMITE DE ENTREGA. La fecha límite de entrega será el: Miércoles 22 de diciembre de 2010 (23:59h hora española) FORMA DE ENTREGA. Las prácticas se entregarán a antonio.fari.so@gmail.com antes de proceder a su defensa. Se deberá enviar un fichero comprimido p2.tar.gz que contendrá: a) código fuente e b) fichero Makefile (el profesor compilará los 4 programas tecleando $make). El asunto del mensaje deberá ser el siguiente: [SO1P2]::[EI]::[Nombre 1er Integrante Grupo][Nombre 2º Integrante Grupo] // de ser sólo un alumno 1 sólo nombre. El nombre del fichero comprimido debe tener los códigos de usuario de la red de docencia concatenados: nombre1.apellido.apellido-nombre2-apellido.apellido.tar.gz La práctica será defendida ante el profesor, en el aula de prácticas. Todos los miembros de cada grupo deberán estar presentes para la defensa, de forma que el profesor pueda revisar su correcto funcionamiento, y realizar comentarios/preguntas a los integrantes del grupo, así como la realización de cambios en el código que se consideren pertinentes. Las prácticas entregadas y que no sean defendidas con solvencia no será bien vistas, y en función de las circunstancias, podrán implicar un no apto para todos los miembros del grupo. Los programas deberán: Compilar correctamente: se usará gcc con la opción -Wall, y no deben contener errores. Ejecutarse correctamente: Seguirá las especificaciones marcadas. Funcionar correctamente. El alumno debe tener en cuenta los valores que devuelvan todas las funciones que utilice (OJO a los valores devueltos por las funciones usadas!!). Evitar la existencia de memory-leaks (el profesor usará valgrind para revisar este aspecto). Se valorará favorablemente el que se evite la repetición innecesaria de código entre los 4 programas a implementar. P.ej: Se puede implementar un módulo semáforos.h/semáforos.c que se encargue de implementar las funciones de manejo de semáforos. Entre ellas: void P(int semid, int sem_i); void V(int semid, int sem_i); void setvalue (int semid, int sem_i, int value); int getvalue (int semid, int sem_i); //sólo para debugging. int loadsemaphores(uint numberofsemaphs, int mode); //crear/acceder Igualmente es aconsejable utilizar un módulo buffer.h/buffer.c que contendrá funciones de creación/manejo del buffer compartido. DETALLES A RECORDAR.

El valor máximo de las prácticas es de 1.5 puntos. Todas las prácticas deben haber recibido la calificación de aptas. Var NOTAS:: Problema de productores/consumidores (búffer limitado). Semáforo mutex = 1 // exclusión mutua en acceso a búffer Semáforo vacio = n; // número de celdas vacías en el búffer Semáforo lleno = 0; //número de celtas llenas en el búffer. Productor Var it: t_item Begin Repeat Producir(it); P(vacio); P(mutex); Añadir it al búffer; V(mutex); V(lleno); Until false End; Consumidor Var it: t_item Begin Repeat P(lleno); P(mutex); It elemento del búffer; V(mutex); V(vacio); Consumir (it); Until false; End