Un semáforo se puede describir como un objeto que consiste en un contador, una lista de espera de procesos, funciones Signal y Wait. El uso más básico del semáforo es inicializarlo en 1. Cuando un subproceso quiere ingresar a una sección crítica, llama e ingresa a la sección. Cuando otro subproceso intenta hacer lo mismo, el sistema operativo lo pondrá en suspensión porque el valor del semáforo ya es cero debido a una llamada anterior a down. Cuando el primer subproceso finaliza con la sección crítica, se activa, lo que activa el otro subproceso que está esperando para entrar.
Lógicamente, el semáforo S es una variable entera que, además de la inicialización, solo se puede acceder a través de dos operaciones atómicas:
- Wait(S) o P : si el valor del semáforo es mayor que 0, disminuya el valor. De lo contrario, espere hasta que el valor sea mayor que 0 y luego disminúyalo.
- Señal(S) o V : Incrementa el valor del Semáforo
Solución de semáforo con espera ocupada:
Si un proceso está en la sección crítica, el otro proceso que intenta ingresar a su sección crítica debe repetir continuamente el código de entrada. Las definiciones clásicas de espera y señal son:
wait (S) { while (S<=0); S--; } signal (S) { S++; }
Implementación de semáforos: sección crítica de n problemas de proceso
Shared Data : semaphore mutex ; // initially mutex=1 Process P : do { wait (mutex) ; <critical section> signal (mutex) ; <remainder section> } while (1)
Solución de semáforo con bloqueo y activación:
en los procesos de problemas de espera ocupada, los procesos desperdician ciclos de CPU mientras esperan ingresar a sus secciones críticas. Modifique la operación de espera en la operación de bloque. El proceso puede bloquearse a sí mismo en lugar de esperar el autobús. Coloque el proceso en la cola de espera asociada con la sección crítica. Modifique la operación de la señal en la operación de activación. Cambia el estado del proceso de espera a listo.
Cuando el proceso ejecuta la operación de espera y encuentra que el valor del semáforo no es positivo, el proceso puede bloquearse. La operación de bloque coloca el proceso en la cola de espera asociada con el semáforo. Un proceso que está bloqueado esperando un semáforo debe reiniciarse cuando el otro proceso ejecuta la operación de señal. El proceso bloqueado debe reiniciarse mediante una operación de reactivación que coloque ese proceso en la cola de espera.
Para implementar el semáforo, definimos el Semáforo como registro:
typedef struct { int value ; struct process *L ; } semaphore ;
Supongamos dos operaciones:
- bloque: suspende el proceso que lo invoca.
- wakeup (P) : reanuda la ejecución del proceso bloqueado (P)
Operaciones de semáforo definidas como:
wait (S) { S.value -- ; if ( S.value < 0 ) { add this process to S.L ; block ; } }
signal (S) { S.value ++ ; if ( S.value <= 0 ) { removes a process P from S.L ; wakeup (P) ; } }
ventajas :
- Los semáforos son fáciles de implementar e independientes de la máquina.
- Las correcciones son fáciles de determinar.
- Los semáforos adquieren muchos recursos simultáneamente
- Puede tener muchas secciones críticas diferentes con diferentes semáforos
- Sin desperdicio de recursos debido a la espera ocupada
Inconvenientes:
- El acceso a los semáforos puede provenir de cualquier parte de un programa
- No hay conexión lingüística entre el semáforo y los datos a los que el semáforo controla el acceso.
- el uso inadecuado de los semáforos conducirá a un punto muerto o inanición
- No hay control ni garantía de uso adecuado
Publicación traducida automáticamente
Artículo escrito por infoutkarsh y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA