TALLER # 7 Semaforos

October 18, 2017 | Author: Cesar Yesid Pineda | Category: Computer Architecture, Areas Of Computer Science, Operating System Technology, Computer Programming, Computing
Share Embed Donate


Short Description

Descripción: Manejo de semaforos en linux...

Description

SISTEMAS OPERATIVOS

TALLER No. 7 SEMAFOROS EN LINUX

Contenido El primer método de sincronización de procesos, es el llamado semáforo. La sincronización de procesos es necesaria en los casos de acceso a un recurso crítico y escaso, para ello el semáforo especifica cuantos procesos puede acceder a dicho recurso en un momento dado. Objetivo Especifico    1.

Introducir al estudiante el concepto de semáforo. Familiarizarse con las funciones de LINUX/UNIX para manejo de semáforos. Resolver problemas relacionados con la sincronización de proceso utilizando semáforos.

Introducción Teórica

Semáforos Los semáforos constituyen un proceso de sincronización de procesos más que de comunicación de información propiamente dicha. Con ellos se pueden resolver problemas de exclusión mutua, en los que un recurso es compartido por varios procesos. Un semáforo, S, no es otra cosa que una variable que puede tomar valores enteros positivos (semáforo en verde) o cero (semáforo en rojo) y que se puede manipular mediante las operaciones Decremento e Incremento:  

Decremento. Si S=0, entonces el proceso que realiza la operación de decremento se bloquea y permanece en estado de espera. Si no, se decrementa una unidad el valor del semáforo S (S=S-1). Incremento. Si existe algún proceso que esté bloqueado por causa de una operación de decremento sobre 5, entonces uno de ellos despierta y no se incrementa el valor del semáforo. En caso contrario se incrementa en una unidad el valor del semáforo S (S=S+1).

En realidad, tanto el valor del incremento como el del decremento pueden ser superiores a la unidad. La forma habitual de utilizar semáforos para resolver problemas de sección critica es como se indica a continuación: Si a una misma sección critica pueden acceder simultáneamente n procesos, se puede resolver el problema utilizando un semáforo con valor inicial igual a n. Entonces, cada proceso que entre en dicha sección critica decrementará el valor del semáforo una unidad.

TALLER No. 7 SEMAFOROS EN LINUX

SISTEMAS OPERATIVOS

Dicho semáforo seguirá teniendo un valor positivo (semáforo en verde) mientras haya menos de n procesos en la sección crítica. Cuando intente acceder a ella el proceso n+1, se encontrará el semáforo con valor cero (semáforo en rojo). Al salir de la sección crítica, un proceso realizará una operación incremento sobre el semáforo, con lo que el proceso bloqueado entrará en esa sección crítica y el semáforo seguirá con valor cero (en rojo) para otros procesos. Este mecanismo comunicación requiere dos condiciones para garantizar que su funcionamiento sea correcto: Las operaciones incremento y decremento han de ser atómicas. Esto significa que el sistema operativo no permite que una operación incremento o decremento pueda ser interrumpida por otra operación incremento o decremento. Así se garantiza que cuando dos procesos compitan por un semáforo solamente uno pueda acceder a modificar su estado. Debe existir algún mecanismo que permita memorizar las peticiones de operaciones decremento no satisfechas y despertar a los procesos en espera. Las llamadas al sistema relacionadas con los semáforos son las que se indican a continuación: 2.

Llamada al Sistema de Semáforos

semget() Crea un semáforo o permite el acceso a uno ya existente. semctl() Realiza operaciones de inicialización y control de semáforos. semop() Realiza operaciones incremento y decremento sobre un semaforo. 3.

Creación y acceso a grupos de semáforos: semget.

En realidad, el sistema operativo LINUX/UNIX no opera con semáforos individuales sino con grupos que pueden constar de uno o más semáforos. La llamada a semget permite crear un grupo de semáforos o acceder a uno ya existente: #include #include #include int semget(key_t key,int nsems,int semflg); Cuando funciona correctamente devuelve un identificador que permite el acceso posterior a los semáforos. Si se produce algún tipo de fallo devuelve el entero -1 y deja en errno el código del error ocurrido. El parámetro key es de tipo key _t (definido en sys/types.h y equivalente a un entero largo). Es una clave que el sistema necesita para organizar las estructuras de datos relacionadas con la comunicación entre procesos. En función de su valor se crea un grupo nuevo o se accede a uno ya existente: 1. Creación de un grupo de semáforos nuevo: se utiliza la

constante IPC_PRIVATE. 2. Acceso a un grupo de semáforos existente: se utiliza la clave de

TALLER No. 7 SEMAFOROS EN LINUX

SISTEMAS OPERATIVOS

dicho conjunto. Esta clave puede obtenerse con la orden ipcs desde el shell del sistema operativo.

El parámetro nsems hace referencia al número total de semáforos que se agrupan bajo el identificador que devuelve semget. El valor semflg es el correspondiente a una máscara de bits que indica el modo de adquisición y los permisos que se otorgan para el acceso al grupo de semáforos (utilizando 4 cifras). Se pueden combinar el modo de adquisición y los permisos utilizando la operación OR entre bits (1). IPC_CREAT es el modo de adquisición que se utiliza cuando se desea crear un nuevo grupo de semáforos. Se puede combinar con los permisos deseados de la siguiente forma: IPC_CREAT|0400 Para acceder a un grupo de semáforos que ya existe en el sistema, no es necesario indicar ningún modo de adquisición especial. Así, para crear 5 semáforos con permisos de lectura y escritura únicamente para el usuario se puede utilizar la siguiente llamada al sistema: #include #include #include int semid; semid=semget(IPC_PRIVATE,5,IPC_CREAT|0600); En la variable entera semid queda almacenado el valor del identificador del grupo de semáforos. 4.

Control de semáforos: semctl.

La llamada al sistema semctl permite realizar operaciones de control sobre un semáforo concreto de un grupo: #include #include #include int semctl (int semid,int semnum,int cmd,semun arg); Donde semid es el identificador del grupo de semáforos y semnum el número de semáforo al que se quiere acceder dentro de los del grupo. El parámetro cmd especifica la operación de control de que se trata: SETVAL. Asignación de un valor a un semáforo. El parámetro arg es el valor que se desea asignar al semáforo en cuestión. De esta manera se puede asignar el valor 3 al semáforo 0 del grupo 4 con la siguiente instrucción: semcti(4,0,SETVAL,3); GETVAL. Obtención del valor de un semáforo. En este caso, semctl devuelve un

TALLER No. 7 SEMAFOROS EN LINUX

SISTEMAS OPERATIVOS

entero con el valor del semáforo. Entonces, el siguiente código permite almacenar en el entero s el valor del semáforo 0 del grupo 4. int s; s=semcti(4,0,GETVAL,0); IPC_RMID. Eliminación de un grupo de semáforos. Si algún proceso está utilizando uno o más semáforos del grupo especificado, la eliminación no tendrá lugar hasta que deje de utilizarlos. Para eliminar el grupo de semáforos 4, la llamada al sistema correspondiente es: semcti(4,0,IPC_RMID,0); El tipo semun corresponde a una unión de datos y aparece definido en el archivo de cabecera sem.h de la forma que se indica: union semun{ int val; struct semid ds *buffer; ushort *array; }; Cuando se produce algún fallo, la llamada a semctl devuelve -1 y deja en errno el código del error producido. 5.

Operaciones Incremento y Decremento: semop.

La llamada a semop permite realizar sobre un semáforo las operaciones incremento (up) y decremento (down) de manera atómica. #include #include #include int semop (int semid,struct sembuf *sops,int nsops}; El parámetro semid corresponde a un identificador de un grupo de semáforos. El puntero sops a estructuras de tipo sembuf contiene las acciones que se han de operar sobre los semáforos. El número total de operaciones que se van a realizar se indica en la variable nsops. La estructura sembuf está definida de la siguiente forma en el archivo de cabecera sem.h: struct sembuf { ushort sem_num; /* Número del semáforo dentro del grupo*/ short sem_op; /* Operación */ short sem flg; /* Máscara de bits */ };

TALLER No. 7 SEMAFOROS EN LINUX

SISTEMAS OPERATIVOS

Si sem_op es positivo, el semáforo sem_num se incrementa en ese valor. Si es negativo, se decrernenta. Si es cero, su valor no se modifica. Cuando se intenta decrementar un semáforo de valor O (semáforo en rojo) el proceso se bloquea a la espera de que otro proceso incremente el valor de dicho semáforo (semáforo en verde). Si la llamada no se realiza con éxito, la función devuelve -1 y deja en errno el código del error que tuvo lugar. Ejemplo:

#include #include #include . . int main (int argc,char *argv[]) { int semid; struct sembuf operacion; /* Creación de un grupo de 2 semáforos */ semid=semget(IPC_PRIVATE,2,IPC_CREAT|060); /* Asignación de valores a la variable operación: */ operacion.sem_num=0; /* Actuar sobre el semáforo 0 */ operacion.sem_op=-1; /* Restar 1 */ operacion.sem_flg=0; /* Ejecución de una operación down sobre el semáforo: */ semop(semid,&operacion,1); } El código anterior permite efectuar una operación decremento de 1 unidad (down) sobre el semáforo 0 dentro de los que estén agrupados bajo el identificador servid. Si el semáforo tiene un valor igual a 0, entonces no se decremento y el proceso permanece bloqueado hasta que otro proceso haga una operación incremento sobre dicho semáforo.

SISTEMAS OPERATIVOS

TALLER No. 7 SEMAFOROS EN LINUX

Taller Propuesto : Ejecute el programa (Sin semáforos) cuyo código fuente se entrega. El objetivo es que el proceso padre muestre en pantalla líneas de diez caracteres '+' y el hijo líneas con diez caracteres 'o'. Debido a una falta de sincronización entre los procesos, ambas salidas se mezclan. Utilizar semáforos para arreglar el problema de forma que el proceso hijo no entre en la sección crítica mientras el padre esté dentro de la suya y, al revés, el proceso padre no debe entrar en la sección crítica mientras el hijo esté dentro de la suya. Además, las secciones críticas de los procesos padre e hijo deben ejecutarse de manera alternativa. #include #include #include int main (int argc, char *argv[]) { int i=0,j,pid; /* Se crea un proceso hijo */ pid=fork(); /* Se comprueba que no hubo error en fork() */ if (pid == -1) { perror("fork!"); exit(-1); } if (pid==0) { /* Proceso HIJO */ while (i
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF