Sistemas Operativos I Práctica 2 -...

37
1 Sistemas Operativos I Práctica 2 Diana Rosario Pérez Marín Marzo 2007 EPS-UAM Continuación de la implementación de msh: Uso de la memoria compartida y de semáforos

Transcript of Sistemas Operativos I Práctica 2 -...

Page 1: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

1

Sistemas Operativos IPráctica 2

Diana Rosario Pérez MarínMarzo 2007

EPS-UAM

Continuación de la implementación de msh:Uso de la memoria compartida y de semáforos

Page 2: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

2

Conceptos teóricos

• Para comunicar a varios procesos en ejecución, el sistema operativo Linuxnos ofrece varias alternativas: usar el valor devuelto por exit, ficheros, pipes o memoria compartida. Nosotros nos vamos a centrar en esta última forma de comunicación, que consiste en crear una zona de memoria común a la que todos los procesos se enganchan y de esta forma, lo que un proceso escribe en ella, lo pueden leer todos los demás.

• Por ejemplo :Memoria compartidaProceso 1 Proceso 2

Escribe :valor = 9

Lee :valor = 9

Valor = 9

Page 3: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

3

Varias instancias de msh compartiendo información común

• En esta práctica continuamos con el desarrollo de nuestro intérprete de comandos. De forma que todos los requisitos exigidos en la práctica anterior se mantienen en esta práctica.

• Con la novedad de que ahora ya no nos vamos a centrar únicamente en una ejecución de msh, sino que vamos a ejecutar varios mshs de forma concurrente. Todos ellos serán procesos padre que vayan lanzando hijos para que vayan ejecutando los comandos que se les pida de forma interactiva o por fichero.

• Habrá un único fichero .msprofile al que todos tendrán acceso y la información de los procesos y las variables la guardarán en un espacio de memoria común (la memoria compartida) de forma que todas las instancias de msh, tengan el mismo valor para todas las variables de entorno. Se definen nuevas variables:

– MAX_NUM_MSHS: número máximo de mshs que se pueden ejecutar en paralelo.– ID_MEMORIA: clave que se usará para identificar la memoria.

Page 4: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

4

Modificaciones a realizar en los comandos propios de msh (I)

• exit: Sigue siendo el comando que se encarga de cerrar unintérprete de comandos (aunque pueden quedar otros ejecutándose). Debe liberar la memoria prestada, esperar a todos los hijos, desengancharse de la memoria compartida y si es ya la última instancia de msh que queda, liberar la memoria compartida.

• msps: Si la memoria compartida de procesos tiene permisos de lectura, lista todos los procesos que estén en ejecución en todas las mshs activas. Mostrando una línea por proceso que sigue el formato:

pid ppid status t_ejec comando idMsh• eVar, rVar y Entorno: Su sintaxis no varía respecto a la práctica

anterior. Tan solo hay que tener cuidado de que ahora sólo se puede ejecutar si se tiene permiso de lectura de la memoria compartida de variables.

Page 5: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

5

Modificaciones a realizar en los comandos propios de msh (II)

• aVar: Si la msh desde donde se ejecuta tiene permisos de escritura en memoria compartida de variables entonces funciona igual que en la práctica anterior, en caso contrario debe dar error.

• bVar: La msh desde donde se ejecuta debe tener permisos de lectura y escritura. En caso contrario, debe dar error.

• eId: A cada uno de los msh que tenemos en ejecución le vamos a asignar un identificador que puede ser su número de pid o bien el valor de un contador que empieza en uno y se va incrementando cada vez que se crea un nuevo msh. El comando eId nos debe mostrar por pantalla el identificador del msh desde donde se ejecuta

• eNum: Muestra por pantalla el número de mshs que se están ejecutando concurrentemente.

Page 6: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

6

Modificaciones a realizar en los comandos propios de msh (III)

• dPermVar: Concede permisos para acceder a la memoria compartida de variables (dPermVar r, concede el permiso de lectura; dPermVar w: concede el permiso de escritura; y, dPermVar: concede ambos permisos).

• dPermProc: Igual que dPermVar pero pero para la memoria de procesos.

• ePermVar: Muestra qué permisos tiene la memoria compartida de variables (ePermVar r, muestra si tiene permiso de lectura; ePermVar w: muestra si tiene el permiso de escritura; y, ePermVar: ambos).

• ePermProc: Igual que ePermVar pero para la memoria de procesos• bPermVar: deniega permisos para acceder a la memoria

compartida de variables (bPermVar r, deniega el permiso de lectura; bPermVar w: deniega el permiso de escritura; y, bPermVar: ambos).

• bPermProc: Igual que bPermVar pero para la memoria compartida de procesos.

Page 7: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

7

Pseudocódigo de msh (I)

• Comprobar argumentos para saber si entra en modo fichero o en modo interactivo o bien si algún error en los argumentos salir.

• Leer el fichero de configuración .msprofile y entonces:– Si es el primer msh que se ejecuta, crear la memoria compartida

reservando espacio para una estructura con información sobre :• El número real de procesos que se han creado.• El número máximo de procesos que se pueden guardar.• El número real de variables de entorno que se están gestionando.• El número máximo de variables que se pueden guardar.• Un array con los identificadores de las instancias de msh de tamaño el máximo

número de mshs que se puedan ejecutar concurremente.• Un array de igual tamaño que el anterior que indique el modo de cada msh:

FICHERO (F) o INTERACTIVO (I).• Un array de tamaño el número de mshs que guarde para cada msh un

contador del número de hijos, que se incremente en cada fork y se decremente en cada wait/waitpid. De forma que cuando su valor llegue a cero esto indique que ya no queda ningún proceso en estado zombi.

Page 8: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

8

Pseudocódigo de msh (II)

• Un array de estructuras variables de tamaño el número máximo de variables.• Un array de estructuras procesos de tamaño el número máximo de procesos.• Un array de permisos de lectura de tamaño el máximo número de mshs.• Un array de permisos de escritura de tamaño el máximo número de mshs.• Un contador del número real de mshs en ejecución (opcional).

– Engancharse a la memoria compartida. Tanto si es la primera instancia de msh como las siguientes, todos los procesos que quieran tener acceso a la memoria compartida, necesitan obtener un puntero a ella.

– Si es la primera instancia de msh, inicializar los campos de la estructura de la memoria con valores por defecto e ir rellenando los campos de las variables con la información leída del fichero .msprofile. Si no es la primera, actualizar únicamente los campos adecuados (como colocar su valor en los arrays e incrementar los contadores pertinentes). Tener en cuenta que no tener permiso de escritura no debe impedir la escritura de las variables leídas de .msprofile.

– Ejecutar los posibles comandos de inicio que hubiera en el fichero .msprofile.

Page 9: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

9

Pseudocódigo de msh ( III )

– Mientras que siga habiendo comandos a ejecutar:• Analizar la línea de comandos. La sintaxis es la misma que en la práctica

anterior. No es necesario guardar los comandos en memoria compartida, pero sí los procesos.

• Identificar el comando. Si el comando es alguno de los comentados en las diapositivas anteriores entonces es el propio padre quien lo ejecuta, en caso contrario crear un hijo para que lo ejecute llamando a execvp (¡el hijo debe desvincularse de la memoria compartida antes de llamar a execvp!).

• Mientras el hijo está ejecutando el comando, el padre guarda la información sobre el proceso en memoria compartida.

• Si es el comando no debe ser ejecutado en background, entonces hacer espera bloqueante con waitpid hasta que termine el proceso.

– Esperar a que todos los hijos terminen. Incluídos los que estén en background y comprobar que el contador de los hijos llega a 0 para que no se queden procesos zombi.

– Liberar todos los recursos prestados.

Page 10: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

10

Vista global

• Ver en el enunciado ejemplo de .msprofile y ficheroScript.

Consola3

./msh ficheroScriptEnganche a mc..OKLect. .msprofile..OKarchivo1msh% exit

consola2

./mshEnganche a mc..OKLect. .msprofile..OKarchivo1msh% dPermVar wPermiso concedido.msh% exit

consola1

./mshCreando mc..OKLect. .msprofile..OKarchivo1

msh% eNumHay 1 msh. en ejec.

msh% exit

Page 11: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

11

Qué es un semáforo ( I )

• Además, en esta práctica nos vamos asegurar que no haya ningún problema de concurrencia en la ejecución de las mshs.

• Para ello vamos a usar semáforos.• Un semáforo no es más que un número entero positivo y es así como hay que

imaginarlo, pero siguiendo la metáfora de un semáforo que estará en rojocuando el valor del entero sea 0 y estará en verde cuando tenga un valor positivo.

• Cuando un proceso toma el semáforo, lo primero que se hace es comprobar el valor del semáforo. Si es 0, entonces se le deja dormido, y sólo cuando otro proceso lo libera e incrementa su valor, se le deja pasar. Lo primero que hace es decrementar el valor para que cuando llegue a 0 se le cierre el paso a todos los demás procesos que vengan por detrás. Por lo tanto para proteger una sección crítica con semáforos se hará :

Down(semaforo)Sección críticaUp(semaforo)

Page 12: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

12

Qué es un semáforo ( II )

• De esta forma se asegura :– La exclusión mutua, esto es, que sólo va a haber un proceso en la

sección crítica.– Un proceso que no está en su sección crítica no puede bloquear

a otros procesos.– El proceso que está en la sección crítica no bloqueará para

siempre al resto, ya que cuando termine de escribir en la memoria compartida entonces liberará el semáforo y el primer proceso de la cola de los que estaban dormidos a la espera de que el semáforo despertara será el que haya ganado el acceso a la sección crítica. Así cuando termine de manipular la memoria compartida liberará el semáforo para que pase al siguiente. Hasta que finalmente pasen todos por esta zona protegida del código.

Page 13: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

13

Tipos de semáforo

• Hay dos tipos de semáforo :– Binarios : Sólo pueden tomar 2 valores, 1 ó 0. De forma que

cuando están a 1 permiten acceder a la zona crítica y cuando están a 0 ya no permiten acceder a ella. Son muy útiles como semáforos mutex para controlar escritura de variables en memoria compartida que sólo permite que 1 proceso esté en la sección crítica.

– N-arios : Se inicializan al número de procesos que se permite que estén en la sección crítica, de forma que cada uno de ellos lo va decrementando al hacer el down y luego cuando llega a 0 ya no permite que pasen ninguno más, hasta que se va liberando. Son muy útiles para operaciones de consulta de la memoria compartida en las que se permite que varios procesos lean de ella siempre que no haya ningún otro proceso escribiendo lo que se controlaría con un semáforo binario.

Page 14: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

14

Operaciones con semáforos

• Down, p, wait o toma_semaforo : Consiste en la petición del semáforo por parte de un proceso que quiere entrar en la sección crítica. Lo que se hace es comprobar si el valor del semáforo es 0 para en ese caso quedarse dormido porque el semáforo está en rojo y habrá otro proceso en la sección crítica. Mientras que si está en un valor positivo entonces el semáforo está en verde y de forma atómica (esto es el planificador no puede dar ahora la ejecución a otro proceso) decrementa el valor del semáforo.

• Up, v, signal o libera_semaforo : Consiste en la liberación del semáforo por parte del proceso que ya ha terminado de trabajar en la sección crítica y por lo tanto de forma atómica también incrementar el valor del semáforo. Por lo que si fuera binario estaría despertando a otro proceso que estuviera esperando en down (al pasar el valor de 0 a 1), si fuera N-ario simplemente incrementa una unidad y si estaba en 0 también significará que lo pone en verde y permitiendo el acceso a la sección crítica al otro proceso.

Page 15: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

15

Llamadas al sistema operativo para trabajar con memoria compartida

• Veamos ahora de qué funciones disponemos :– shmget : Crear la zona de memoria compartida– shmat : Engancharse a la zona de memoria compartida– shmdt : Desengancharse de la zona de memoria compartida– shmctl : Operaciones de control e información sobre la memoria

compartida

• Todas ellas por razones de portabilidad a otros sistemas operativos se deben encapsular en un fichero aparte ( por ej. memoria.c ) con su correspondiente archivo de cabecera ( por ej. memoria.h ) que no deben contener información referente a esta práctica.

• En las siguientes transparencias estudiaremos sus prototipos y las librerías que hay que incluir para poderlas usar.

Page 16: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

16

shmget

• Hay que incluir las librerías :– #include <sys/ipc.h>– #include <sys/shm.h>

• Sirve para crear una zona de memoria compartida, y su prototipo es :– int shmget ( key_t key, int size, int shmflg ) ;– El valor de retorno es el identificador de la zona de memoria compartida si todo va

bien, -1 si error y errno coge el número de error encontrado. Importante distinguir el valor EEXIST de errno puesto que no se debe considerar error como tal, ya que lo que indica es que la memoria compartida ya existía y no se está creando nueva.

– Los argumentos son :• key_t key : Clave para crear la memoria compartida ( MEMID ), la misma para

todos los procesos que quieren acceder a esta zona común.• int size : Tamaño a reservar ( sizeof de la estructura ).• int shmflg : Opciones de configuración. Se hace un OR entre ellas. Ejemplos :

– IPC_CREAT sirve para crear un nuevo segmento– IPC_EXCL para asegurarse que no existía anteriormente– Permisos : SHM_R para leer y SHM_W para escribir (para todas las mshs*) .

* los permisos los gestionamos nosotros con los arrays para la lectura y la escritura

Page 17: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

17

shmat

• Hay que incluir las librerías :– #include <sys/ipc.h>– #include <sys/shm.h>– #include <sys/types.h>

• Sirve para engancharse a una zona de memoria compartida. Prototipo :– char * shmat ( int shmid, char * shmaddr, int shmflg ) ;– El valor de retorno es el puntero a la zona de memoria compartida si todo va bien,

NULL si error y errno coge el número de error encontrado. – Los argumentos son :

• int shmid : Identificador devuelto por shmget.• char * shmaddr : Como realloc se le podría indicar un puntero a una zona de

memoria ya existente. Por defecto, este argumento se pasa a NULL.• int shmflg : Opciones de configuración. Se hace un OR entre ellas. Ejemplos :

– SHM_R permiso para leer.– SHM_W permiso para escribir. condicionado a shmget

Page 18: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

18

shmdt

• Hay que incluir las librerías :– #include <sys/ipc.h>– #include <sys/shm.h>– #include <sys/types.h>

• Sirve para desengancharse de una zona de memoria compartida. Prototipo :– int shmdt ( char * shmaddr ) ;– El valor de retorno es 0 si todo va bien, -1 si error y errno coge el número

de error encontrado. – El argumento es char * shmaddr : Puntero a la zona de memoria

compartida de la que nos queremos desenganchar. Se suele pasar con un casting a ( char * ) para compatibilizar argumentos.

Page 19: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

19

shmctl

• Hay que incluir las librerías :– #include <sys/ipc.h>– #include <sys/shm.h>

• Sirve entre otras funciones de control sobre la memoria compartida, para eliminarla definitivamente ( siempre y cuando todos los procesos se hayan desenganchado de ella). Su prototipo es :– int shmctl ( int shmid, int comando, struct shmid_ds * buf ) ;– El valor de retorno es 0 si todo va bien, -1 si error y errno coge el número

de error.– Los argumentos son :

• int shmid : Identificador devuelto por shmget.• int comando : IPC_RMID para eliminarla.• struct shmid_ds * buf : Estructura con información de control. Por

defecto se pasa a NULL cuando no se quiere trabajar con ella.

Page 20: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

20

Ejemplo básico de creación de memoria compartida ( I )

#include <stdio.h>

#include <sys/ipc.h>#include <sys/shm.h>

#include <sys/types.h>#include <errno.h>

int main () {

int shm ; /* identificador de la zona de memoriacompartida */int * dir ; /* direccion de enlace de la memoria con los datos */int * numero ; /* numero que guardamos en la memoria compartida */

printf(“Estoy creando la memoria compartida\n") ;

Page 21: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

21

Ejemplo ( II )

/* creo la zona de memoria compartida */shm = shmget(3000, sizeof(int), IPC_CREAT|IPC_EXCL|SHM_R|SHM_W) ;if ( shm == -1 && errno == EEXIST)

shm = shmget(3000, sizeof(int), SHM_R|SHM_W) ;printf ( “Cree la zona de memoria %d\n", shm) ;/* lo enlazo a un proceso */dir = (int *) shmat ( shm, NULL, 0) ;if ( dir == (int *)-1) {

perror("error de enlace\n") ;exit(-1) ;

} /* utilizo la informacion */numero = (int *) dir ;*numero = 0 ;printf("%d", *numero) ;

Page 22: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

22

Ejemplo ( III )

/* libero la memoria */if ( shmdt(dir) == -1) {

perror("error de liberacion\n") ;exit(-1) ;

}else{

if (shmctl(shm, IPC_RMID, 0) == -1) {

perror("error de borrado fisico\n") ;exit(-1) ;

}}exit(0) ;

}

Page 23: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

23

Funciones de semáforos

• Veamos ahora cómo se implementan los semáforos en Linux. Para usarlos lo primero que hay que hacer es incluir las librerías <sys/types.h>, <sys/ipc.h> y <sys/sem.h>, las funciones que vamos a usar son semget, semop y semctl. Que como en la práctica anterior no usaremos directamente para que el código sea portable a otrossistemas operativos sino que las encapsularemos en otras funciones en un archivo semaforo.c y su correspondiente archivo de cabecera semaforo.h. En semaforo.h además de incluir las librerías y los prototipos de las funciones que encapsularan las llamadas al sistema operativo, tenemos que escribir:

#if defined ( __GNU_LIBRARY__) && !defined ( _SEM_SEMUN_UNDEFINED )#else

union semun {int valor ; /* valor para SETVAL */struct semid_ds * buf ; /* buffer para IPC_STAT, IPC_SET */unsigned short int * array ; /* array para GETALL, SETALL */struct seminfo * __buf ; /* buffer para IPC_INFO */} ;

#endif

Page 24: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

24

semget ( I )

• Sirve para crear el array de semáforos. Siempre se crea un array de semáforos aunque sólo queramos usar 1, se creará un array de un solo elemento y para referirte a él será el semáforo número 0.

• Igual que con shmget, se debe distinguir entre el primer msh que es el que debe crear el array de semáforos usando las opciones IPC_CREAT|IPC_EXCL|SHM_R|SHM_W, y el resto de mshs que sólo la llaman para obtener el identificador del array de semáforos con los permisos de lectura y escritura ( SHM_R|SHM_W ).

• Su prototipo es : int semget ( key_t key, int nsems, int flags )• Donde el int de retorno es el identificador del array de semáforos

creados si no ha habido ningún error, -1 si lo ha habido con errnoindicando qué es lo que ha ocurrido ( distinguir EEXIST ).

Page 25: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

25

semget ( II )

• Los argumentos que recibe son :– key_t key : La clave que todos los procesos deben pasar a la

función. Debe estar definido en el .h por ejemplo como CLAVE_SEMAFORO.

– int nsems : El número de semáforos que se quieren crear– int flags : Opciones de creación, OR entre IPC_CREAT, IPC_EXCL,

SHM_R y SHM_W• Cuidado que la creación de un semáforo es independiente de su

inicialización y usar un semáforo sin inicializar puede tener resultados catastróficos, por lo que hay que asegurarse de inicializar los semáforos inmediatamente después de crearlos.

• Veamos ahora un ejemplo de código que usa semget :

Page 26: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

26

semget ( III )

#define CLAVE_SEMAFORO 2000int semid ;

semid = semget( CLAVE_SEMAFORO, 1, IPC_CREAT|IPC_EXCL|SHM_R|SHM_W); if ( semid == -1 ){

if ( errno == EEXIST )semid = semget( CLAVE_SEMAFORO, 1, SHM_R|SHM_W ) ;

else {perror(“semget”);exit(errno); }

}else printf(“Soy el primero que crea el semáforo con identificador %d\n”, semid);

Page 27: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

27

semop ( I )

• Implementa las operaciones de down y up. Su prototipo es :int semop ( int semid, struct sembuf * sops, unsigned nsops )

• Donde el int del retorno es para control de errores.• Los argumentos son :

– int semid : Es el identificador devuelto por semget.– unsigned nsops : El número de operaciones a realizar sobre el

semáforo– struct sembuf * sops : Es una estructura con 3 campos :

• sem_num : El número de semáforo con el que queremos trabajar.• sem_op : La operación a realizar, que se indica con un número

– Positivo : Si se quiere liberar al semáforo ( up ), ya que lo que hace es incrementar su valor.

– Negativo : Si se quiere tomar el semáforo ( down ) ya que lo que hace es decrementar su valor.

– 0 : Si lo que se quiere el bloquear el semáforo hasta que tenga un valor 0.

Page 28: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

28

semop ( II )

• sem_flag : Flags para configurar la ejecución de la operación – SEM_UNDO : Para que cuando el proceso haga exit se nivelen los semáforos y no

haya problemas de que deje bloqueados a otros procesos.– IPC_NOWAIT : Para que no se quede bloqueado y vuelva del down aunque el

semáforo sea 0.

• Ejemplo de pseudocódigo de lo que hace semop internamente :

libera_semaforo ( int sem ) {if ( hay procesos durmiendo )

despierta al primerosem++ ;

}

coge_semaforo ( int sem ) {if ( sem es 0 )

duerme hasta que sem != 0 ;

else sem-- ;}

Page 29: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

29

semop ( III ). Ejemplo de código de down

struct sembuf pbuf ;

pbuf.sem_num = 0 ;pbuf.sem_op = -1 ;pbuf.sem_flg = SEM_UNDO ;

if ( semop(semid, &pbuf, 1 ) == -1 ){

perror(“semop:”);return ERROR ;

}

Page 30: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

30

semop ( IV ). Ejemplo de código de up

struct sembuf vbuf ;

vbuf.sem_num = 0 ;vbuf.sem_op = 1 ;vbuf.sem_flg = SEM_UNDO ;

if ( semop(semid, &vbuf, 1 ) == -1 ){

perror(“semop:”);return ERROR ;

}

Page 31: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

31

semctl ( I )

• Sirve para inicializar, obtener información o eliminar el array de semáforos. Su prototipo es : int semctl ( int semid, int semnum, intcomando, union semun arg )

• Donde el valor de retorno es para control de errores o el retorno de determinados comandos como GETVAL o GETNCNT.

• Los argumentos son :– int semid : Valor devuelto por semget.– int comando : Puede ser GETNCNT ( para saber cuántos procesos están

esperando en el semáforo ), GETALL ( para obtener los valores de todos los semáforos del array ), GETVAL ( para uno ), SETALL ( para inicializar todos los semáforos del array ), SETVAL ( para uno ), IPC_RMID ( para borrar el array ).

– int semnum : El número del semáforo sobre el que queremos trabajar. Se ignora si se usa GETALL/SETALL que es para todos.

Page 32: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

32

semctl ( II )

– union semun arg : Estructura con los campos• val : El valor para SETVAL • struct semid_ds * buf : Información para IPC_STAT e IPC_SET• unsigned short * array : Array de valores para GETALL y SETALL.

• Ejemplos de código donde se usa semctl :– Para inicializar el array :

union semun carg ;carg.array = array ; // en array los valores a los que queremos inicializar los semif ( semctl( semid, 0, SETALL, carg ) == -1 ) ERROR else OK

– Para saber si hay procesos esperando en un semáforo :numero = semctl ( semid, 1, GETNCNT, carg )

– Para eliminar el array de semáforos :semctl ( semid, 0, IPC_RMID, NULL )

Page 33: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

33

ipcs / icrpm

• De gran utilidad para esta práctica son estos dos comandos :– ipcs : Se teclea ipcs y nos muestra los segmentos de memoria

compartida y semáforos que están reservados.– ipcrm : Nos permite eliminar manualmente cualquier segmento de

memoria compartida ( shm ), cola de mensajes ( msg ) o array de semáforos ( sem ) que por un fallo del programa no se haya eliminado automáticamente. Para memoria compartida se ejecuta : ipcrm shmidMemoria y para semáforos: ipcrm sem idSemaforo

• Un ejemplo de uso sería :– ipcs ( y así averiguamos el identificador de la memoria compartida )– ipcrm shm id ( y sí ya se han terminado todos los procesos enganchados

a la memoria compartida desaparece )

Page 34: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

34

Pasos orientativos para resolver la práctica

• 1°. Familiarizarse con las funciones de creación, modificación y liberación de la memoria compartida y de semáforos. Codificar memoria.c, memoria.h, semaforo.c y semaforo.h. Modificar el makefile para tener en cuenta estos nuevos ficheros.

• 2º. Copiar los ficheros de la práctica anterior en un nuevo directorio para asegurarnos que seguimos teniendo la versión anterior.

• 3º. Modificar main.c para que se tenga en cuenta que ahora se trabaja con memoria compartida y con semáforos.

• 4º. Modificar func.c para tener en cuenta los nuevos comandos y la gestión de la memoria compartida.

• ¡Importante! Asegurarnos de eliminar posibles memorias compartidas que se hayan quedado sin borrar antes de la siguiente ejecución.

Page 35: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

35

Control de errores y mejoras

• Control de errores:– Controlar los retornos de todas las funciones de manejo de la memoria

compartida y los semáforos.– En general, robustecer el código frente a cualquier posible error que ocurra

y asegurar que se dejará la máquina cómo estaba antes de que se ejecutase alguna instancia de msh.

• Mejoras:– Cualquiera de las mejoras de la práctica anterior, son aplicables aquí. En

general, se deja abierta la posibilidad de mejorar el código para que se parezca lo máximo posible a un intérprete de comandos Linux.

– IPC_NOWAIT para que en el caso de que el código se vaya a quedar bloqueado en un punto nos muestra antes un mensaje informándonos.

– Usar memoria dinámica compartida.– Usar algoritmos como lectores/escritores o mejores para no hacer todos los

acceso bloqueantes, sólo cuando 1 escribe, que los demás no lean, pero permitir que hay lecturas concurrentes.

Page 36: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

36

Problema lector/escritor. Teoría ( I )

• Vamos a ver el problema del lector/escritor en el que tenemos procesos con una base de datos común y unos quieren leer de ella y otros escribir. Al igual que en la práctica no se permite que mientras que están leyendo otro escriba, aunque si leer puesto que esto no supone ninguna modificación de la memoria compartida, y tampoco se permite que varios estén escribiendo.

• Para resolverlo se usan 2 semáforos binarios :– mutex : Que controla la escritura de la variable que indica el número de lectores (

numLectores ). De forma que si hay algún lector ya no puede haber escritor y cuando ya no haya lectores ya puede entrar el escritor.

– db : Que controla el acceso a la base de datos por parte tanto de los lectores como los escritores. Si está a 1 entonces es que no hay nadie escribiendo y pueden entrar tantos lectores como quieran a consultar la base de datos. Si es 0 para a los lectores porque el escritor está modificando la base de datos.

Page 37: Sistemas Operativos I Práctica 2 - arantxa.ii.uam.esarantxa.ii.uam.es/~so1/0607/Practicas/Enunciados/presentaPractica2.pdf · 3 Varias instancias de msh compartiendo información

37

Problema lector/escritor. Pseudocódigo ( II )

semaforo mutex = 1semaforo db = 1int numLectores = 0

Escritorwhile ( 1 ){

down(db) ;escribir up(db) ;

}

Lectorwhile ( 1 ){

down( mutex ) ;numLectores++ ;if ( numLectores == 1 )

down(db) ;up(mutex);leerdown(mutex);numLectores-- ;if ( numLectores == 0 )

up(db);up(mutex); }