UNIVERSIDAD NACIONAL AGRARIA DE LA SELVA
Facultad de Ingeniería en Informática y Sistemas
ESCUELA ACADÉMICA PROFESIONAL DE INGENIERÍA EN
INFORMÁTICA Y SISTEMAS
INFORME ACADÉMICO
SISTEMAS OPERATIVOS
“SEMAFOROS”
ASIGNATURA: Sistemas Operativos I
Tingo maría – Perú
Noviembre 2022
2
ÍNDICE
INTRODUCCIÓN.......................................................................3
DESARROLLO............................................................................5
1. SEMAFOROS..........................................................................................................5
2. FUNCIONAMIENTO DE LOS SEMÁFOROS......................................................6
3. EJEMPLOS DE USO DE SEMÁFOROS................................................................8
4. DIFERENCIA ENTRE DEADLOCK Y STARVATION EN OS.........................10
4.1 GRÁFICA COMPARATIVA..............................................................................10
4.2 DEFINICIÓN DE PUNTO MUERTO...............................................................11
4.3 DEFINICIÓN DE INANICIÓN..........................................................................12
4.4 DIFERENCIAS CLAVE ENTRE EL PUNTO MUERTO Y EL HAMBRE
EN EL SISTEMA OPERATIVO...................................................................................12
5. TIPOS DE SEMÁFOROS......................................................................................13
A) SEMAFOROS BINARIO.................................................................................13
B) SEMAFOROS CON MULTIPLES VARIABLES........................................13
6. VENTAJAS E INCONVENIENTES.....................................................................14
7. GRANULARIDAD...............................................................................................15
CONCLUSIONES.....................................................................15
APÉNDICE................................................................................16
BIBLIOGRAFÍA.......................................................................23
3
INTRODUCCIÓN
Esta era la situación en 1965, cuando E. W. Dijkstra (1965) sugirió el uso de una variable
entera para contar el número de señales de despertar, guardadas para un uso futuro. En su
propuesta introdujo un nuevo tipo de variable, al cual él le llamó semáforo. Un semáforo
podría tener el valor 0, indicando que no se guardaron señales de despertar o algún valor
positivo si estuvieran pendientes una o más señales de despertar. Dijkstra propuso que se
tuvieran dos operaciones, down y up (generalizaciones de sleep y wakeup, respectivamente).
La operación down en un semáforo comprueba si el valor es mayor que 0. De ser así,
disminuye el valor (es decir, utiliza una señal de despertar almacenada) y sólo continúa. Si el
valor es 0, el proceso se pone a dormir sin completar la operación down por el momento. Las
acciones de comprobar el valor, modificarlo y posiblemente pasar a dormir, se realizan en
conjunto como una sola acción atómica indivisible. Se garantiza que, una vez que empieza
una operación de semáforo, ningún otro proceso podrá acceder al semáforo sino hasta que la
operación se haya completado o bloqueado. Esta atomicidad es absolutamente esencial para
resolver problemas de sincronización y evitar condiciones de carrera. Las acciones atómicas,
4
en las que un grupo de operaciones relacionadas se realizan sin interrupción o en definitiva no
se realizan, son en extremo importantes en muchas otras áreas de las ciencias
computacionales también.
La operación up incrementa el valor del semáforo direccionado. Si uno o más procesos
estaban inactivos en ese semáforo, sin poder completar una operación down anterior, el
sistema selecciona uno de ellos (al azar) y permite que complete su operación down. Así,
después de una operación up en un semáforo que contenga procesos dormidos, el semáforo
seguirá en 0 pero habrá un proceso menos dormido en él. La operación de incrementar el
semáforo y despertar a un proceso también es indivisible. Ningún proceso se bloquea al
realizar una operación up, de igual forma que ningún proceso se bloquea realizando una
operación wakeup en el modelo anterior.
Como punto adicional, en su artículo original, Dijsktra utilizó los nombres P y V en vez de
down y up, respectivamente. Como éstos no tienen un significado nemónico para las personas
que no hablan holandés y sólo tienen un significado marginal para aquellos que lo hablan
Proberen (intentar) y Verhogen (elevar, elevar más)], utilizaremos los términos down y up en
su defecto. Éstos se introdujeron por primera vez en el lenguaje de programación Algol 68.
(TANENBAUM & MAARTEN, 2009)
DESARROLLO
1. SEMAFOROS
Un semáforo es una variable especial (o tipo abstracto de datos) que constituye el método
clásico para restringir o permitir el acceso a recursos compartidos (por ejemplo, un recurso de
almacenamiento del sistema o variables del código fuente) en un entorno de
multiprocesamiento (en el que se ejecutarán varios procesos concurrentemente). Fueron
inventados por Edsger Dijkstra en 1965 y se usaron por primera vez en el sistema operativo
THEOS. Los semáforos permiten al programador asistir al planificador del sistema operativo
en su toma de decisiones de manera que permiten sincronizar la ejecución de dos o más
procesos, a diferencia de los cerrojos, los semáforos nos ofrecen un mecanismo de espera no
ocupada.
Los semáforos son un tipo de datos que están compuestos por dos atributos:
5
Un contador, que siempre vale >= 0.
Una cola de procesos inicialmente vacía.
Y disponen de dos operaciones básicas que pasamos a describir en pseudocódigo:
Nótese que siempre que queramos forzar una transición de un proceso ha estado bloqueado, tenemos
que hacer que dicho proceso realice una operación down sobre un semáforo cuyo contador vale cero.
El otro uso de los semáforos es para la sincronización. Los semáforos vacías y llenas se
necesitan para garantizar que ciertas secuencias de eventos ocurran o no. En este caso,
aseguran que el productor deje de ejecutarse cuando el búfer esté lleno y que el consumidor
deje de ejecutarse cuando el búfer esté vacío. Este uso es distinto de la exclusión mutua.
(1984.lsi.us.es, 2020)
2. FUNCIONAMIENTO DE LOS SEMÁFOROS
Dos o más procesos pueden cooperar por medio de simples señales, de forma que se pueda
obligar a detenerse a un proceso en una posición determinada hasta que reciba una señal
específica. Cualquier requisito complicado de coordinación puede satisfacerse por medio de la
estructura de señales adecuada. Para la señalización, se usan variables especiales llamadas
semáforos. Para transmitir una señal por el semáforo, los procesos ejecutan la primitiva
signal(s). Para recibir una señal del semáforo, los procesos ejecutan la primitiva wait(s); si la
6
señal correspondiente aún no se ha transmitido, el proceso es suspendido hasta que tenga
lugar la transmisión. Para lograr el efecto deseado, se pueden contemplar los semáforos como
variables que tienen un valor entero sobre el que se definen las tres operaciones siguientes:
Un semáforo debe inicializarse con un valor no negativo.
La operación wait decrementa el valor del semáforo. Si el valor del semáforo se hace
negativo, el proceso que ejecuta el wait se bloquea.
La operación signal incrementa el valor del semáforo. Si el valor no es positivo, se
desbloquea a un proceso bloqueado por una posición wait.
Las primitivas wait y signal se suponen atómicas, es decir, no pueden ser interrumpidas y
cada rutina puede considerarse como un paso indivisible. Una versión más limitada es el
semáforo binario, que sólo puede tomar los valores 0 y 1. En principio los semáforos binarios
son más sencillos de implementar y tienen la misma potencia de expresión que los semáforos
generales. Tanto en los semáforos como en los semáforos binarios se emplea una cola para
mantener los procesos esperando en el semáforo. La política más equitativa mediante la cual
se quitan los procesos de dicha cola es la FIFO. La única exigencia estricta es que un proceso
no debe quedar retenido en la cola de un semáforo indefinidamente porque otros procesos
tengan preferencia. Figura 2.
Generalmente operadores como WAIT y SIGNAL operan en los semáforos de la siguiente
manera. Cuando un proceso ejecuta un operador WAIT que tiene un valor de semáforo en 0,
ese proceso se bloquea; si el valor es mayor que cero, el valor del semáforo es disminuido en
1 y el proceso continuo. Cuando un proceso ejecuta un operador SIGNAL y hay procesos
bloqueados (WAITING), uno de estos procesos es activado (puesto en la cola de listos). Si no
hay procesos esperando el valor del semáforo se incrementa en 1. Se asume que procesos
bloqueados por semáforos pierden el procesador y entran en una cola de espera (WAITING
QUEUE) en vez de producir BUSY WAITING. También se asume que la cola de espera es
FIFO. (NANCY QUINTERO & LOPEZ, 2011)
3. EJEMPLOS DE USO DE SEMÁFOROS
Ejemplo 1:
¿Cómo resolver el problema del productor-consumidor mediante el uso de semáforos?
7
Los semáforos resuelven el problema de pérdida de señales de despertar, como se muestra
en la figura 3. Para que funcionen de manera correcta, es esencial que se implementen de una
forma indivisible. Lo normal es implementar up y down como llamadas al sistema, en donde
el sistema operativo deshabilita brevemente todas las interrupciones, mientras evalúa el
semáforo, lo actualiza y pone el proceso a dormir, si es necesario. Como todas estas acciones
requieren sólo unas cuantas instrucciones, no hay peligro al deshabilitar las interrupciones. Si
se utilizan varias CPUs, cada semáforo debe estar protegido por una variable de candado, en
donde se utilicen las instrucciones TSL o XCHG para asegurar que sólo una CPU a la vez
pueda examinar el semáforo. Asegúrese de comprender que el uso de TSL o XCHG, para
evitar que varias CPUs tengan acceso al semáforo al mismo tiempo, es algo muy distinto al
caso en el que el productor o el consumidor están en espera ocupada, esperando a que el otro
vacíe o llene el búfer. La operación de semáforo sólo tarda unos cuantos microsegundos,
mientras que el productor o el consumidor podrían tardarse una cantidad de tiempo arbitraria
y extensa.
Esta solución utiliza tres semáforos: uno llamado llenas para contabilizar el número de
ranuras llenas, otro llamado vacías para contabilizar el número de ranuras vacías y el último
llamado mutex, para asegurar que el productor y el consumidor no tengan acceso al búfer al
mismo tiempo. Al principio llenas es 0, vacías es igual al número de ranuras en el búfer y
mutex es 1. Los semáforos que se inicializan a 1 y son utilizados por dos o más procesos para
asegurar que sólo uno de ellos pueda entrar a su región crítica en un momento dado se llaman
semáforos binarios. Si cada proceso realiza una operación down justo antes de entrar a su
región crítica y una operación up justo después de salir de ella, se garantiza la exclusión
mutua. Ahora que tenemos una buena primitiva de comunicación entre procesos a nuestra
disposición, volvamos a analizar la secuencia de interrupción de la figura 1. En un sistema
que utiliza semáforos, la forma natural de ocultar las interrupciones es asociar un semáforo
(que al principio es 0) con cada dispositivo de E/S. Justo después de iniciar un dispositivo de
E/S, el proceso administrativo realiza una operación down en el semáforo asociado, con lo
cual se bloquea de inmediato. Cuando entra la interrupción, el manejador de interrupciones
realiza una operación up en el semáforo asociado, lo cual hace que el proceso relevante esté
listo para ejecutarse de nuevo. En este modelo, el paso 5 de la figura 1 consiste en realizar una
operación up en el semáforo del dispositivo, de manera que en el paso 6 el planificador pueda
ejecutar el administrador de dispositivos. Desde luego que, si hay varios procesos listos en ese
momento, el planificador puede optar por ejecutar un proceso aún más importante a
8
continuación. Más adelante en este capítulo analizaremos algunos de los algoritmos que se
utilizan para la planificación. En el ejemplo de la figura 3, en realidad hemos utilizado
semáforos de dos maneras distintas. Esta diferencia es lo bastante importante como para
recalcarla explícitamente. El semáforo mutex se utiliza para la exclusión mutua. Está diseñado
para garantizar que sólo un proceso pueda leer o escribir en el búfer y sus variables asociadas
en un momento dado. Esta exclusión mutua es requerida para evitar un caos. En la siguiente
sección estudiaremos la exclusión mutua y cómo podemos lograrla.
El otro uso de los semáforos es para la sincronización. Los semáforos vacías y llenas se
necesitan para garantizar que ciertas secuencias de eventos ocurran o no. En este caso,
aseguran que el productor deje de ejecutarse cuando el búfer esté lleno y que el consumidor
deje de ejecutarse cuando el búfer esté vacío. Este uso es distinto de la exclusión mutua.
(TANENBAUM & MAARTEN, 2009)
Ejemplo 2:
(github, 2017)Ejercicio cena de los filósofos que simula una cena con semáforos. Un
filósofo comerá si tiene los dos cubiertos de sus lados libres. Si no está comiendo, estará
pensando. Un filósofo comerá o pensará un número aleatorio de segundos. Figura 6.
4. DIFERENCIA ENTRE DEADLOCK Y STARVATION EN OS
(gadget-info.com, 2019)Deadlock y Starvation son las condiciones donde los procesos que
solicitan un recurso se han retrasado por mucho tiempo. Aunque el punto muerto y la
inanición son diferentes entre sí en muchos aspectos. El interbloqueo es una condición en la
que ningún proceso procede de la ejecución y cada uno espera los recursos que han sido
adquiridos por los otros procesos. Por otro lado, en Hambre, el proceso con alta prioridad
utiliza continuamente los recursos que impiden que el proceso de baja prioridad adquiera los
recursos. Discutamos algunas diferencias más entre el interbloqueo y la inanición con la
ayuda del cuadro de comparación que se muestra a continuación.
4.1 GRÁFICA COMPARATIVA
Bases para Comparación Punto muerto Inanición
BASIC El hambre es donde los
El interbloqueo es donde no procesos de baja prioridad se
procede ningún proceso y se bloquean, y el proceso de
9
bloquea.
alta prioridad continúa.
La ocurrencia de exclusión
Cumplimiento de
Condición de levantamiento mutua, espera y espera, no
prioridades, gestión de
preferencia y espera circular
recursos no controlada.
simultáneamente.
Otro nombre Espera circular. Lifelock.
En el punto muerto, los En la inanición, los recursos
Recursos recursos solicitados son solicitados son utilizados
bloqueados por los otros continuamente por procesos
procesos. de alta prioridad.
Evitando la exclusión mutua,
Prevención espera y espera, y espera Envejecimiento.
circular y permite la
prevención.
4.2 DEFINICIÓN DE PUNTO MUERTO
El punto muerto es una situación en la que los diversos procesos en la CPU compiten por
la cantidad finita de recursos disponibles dentro de la CPU. Aquí, cada proceso contiene un
recurso y espera para adquirir un recurso que se mantiene en algún otro proceso. Todos los
procesos esperan los recursos de forma circular. En la imagen a continuación, puede ver que
el Proceso P1 ha adquirido el recurso R2 solicitado por el proceso P2 y el Proceso P1 solicita
el recurso R1, que nuevamente es retenido por R2. Así que el proceso P1 y P2 forman un
punto muerto.
El interbloqueo es un problema común en los sistemas operativos de multiprocesamiento, los
sistemas distribuidos y también en los sistemas de computación en paralelo. Hay cuatro
condiciones que deben ocurrir simultáneamente para aumentar la condición de interbloqueo,
que son la exclusión mutua, la espera y la espera, la no preferencia y la espera circular.
Exclusión mutua: solo un proceso a la vez puede usar un recurso si otro proceso
solicita el mismo recurso, tiene que esperar hasta que el proceso que usa el recurso lo
libere.
Retener y esperar: Un proceso debe estar reteniendo un recurso y esperando para
adquirir otro recurso que esté sujeto a otro proceso.
Sin preferencia: el proceso que contiene los recursos no se puede anticipar. El proceso
que contiene el recurso debe liberar el recurso voluntariamente cuando haya
completado su tarea.
10
Espera circular: el proceso debe esperar los recursos de forma circular. Supongamos
que tenemos tres procesos {P0, P1, P2}. El P0 debe esperar el recurso en poder de P1;
P1 debe esperar para adquirir el recurso retenido por el proceso P2, y P2 debe esperar
para adquirir el proceso retenido por P0.
Aunque hay algunas aplicaciones que pueden detectar los programas que pueden quedar
bloqueados. Pero el sistema operativo nunca es responsable de prevenir los puntos muertos.
Es responsabilidad de los programadores diseñar programas sin interbloqueo. Se puede hacer
evitando las condiciones anteriores que son necesarias para que se produzca un interbloqueo.
4.3 DEFINICIÓN DE INANICIÓN
La inanición se puede definir como cuando una solicitud de proceso para un recurso y ese
recurso ha sido utilizada continuamente por los otros procesos, entonces el proceso de
solicitud se enfrenta a la inanición. En la inanición, un proceso listo para ejecutarse espera a
que la CPU asigne el recurso. Pero el proceso debe esperar indefinidamente, ya que los otros
procesos bloquean continuamente los recursos solicitados.
El problema de la inanición generalmente ocurre en el algoritmo de planificación de
prioridad. En el algoritmo de planificación de prioridad, al proceso con mayor prioridad
siempre se le asigna el recurso, lo que evita que el proceso de menor prioridad obtenga el
recurso solicitado.
El envejecimiento puede resolver el problema de la inanición. El envejecimiento aumenta
gradualmente la prioridad del proceso que ha estado esperando durante mucho tiempo los
recursos. El envejecimiento impide que un proceso con baja prioridad espere indefinidamente
un recurso.
4.4 DIFERENCIAS CLAVE ENTRE EL PUNTO MUERTO Y EL HAMBRE EN EL
SISTEMA OPERATIVO
En un punto muerto, ninguno de los procesos procede a la ejecución, cada proceso se bloquea
mientras esperan los recursos adquiridos por el otro proceso. Por otro lado, la inanición es una
condición en la que los procesos que poseen mayor prioridad pueden adquirir los recursos
continuamente al evitar que los procesos de baja prioridad adquieran recursos, lo que resulta
en un bloqueo indefinido de los procesos de baja prioridad.
El interbloqueo se produce cuando se producen cuatro condiciones de exclusión mutua,
espera y espera, no preferencia y espera circular simultáneamente. Sin embargo, la
inanición se produce cuando se han aplicado las prioridades del proceso al asignar recursos,
o hay una gestión de recursos no controlada en el sistema.
El interbloqueo se suele llamar con el nombre circular de espera, mientras que la inanición
se denomina bloqueo vivido.
En Deadlock, los recursos son bloqueados por el proceso, mientras que, en inanición, los
procesos son utilizados continuamente por los procesos con alta prioridad.
El interbloqueo se puede evitar evitando las condiciones como la exclusión mutua, la espera y
la espera, la espera circular y permitiendo la anticipación de los procesos que mantienen los
recursos durante mucho tiempo. Por otro lado, la inanición se puede prevenir con
el envejecimiento.
11
5. TIPOS DE SEMÁFOROS
A) SEMAFOROS BINARIO
Un tipo simple de semáforo es el binario, que puede tomar solamente los valores 0 y 1. Se
inicializan en 1 y son usados cuando solo un proceso puede acceder a un recurso a la vez.
Cuando el recurso está disponible, un proceso accede y decrementa el valor del semáforo con
la operación P. El valor queda entonces en 0, lo que hace que si otro proceso intenta
decrementarlo tenga que esperar. Cuando el proceso que decremento el semáforo realiza una
operación, algún proceso que estaba esperando comienza a utilizar el recurso. Solo puede
tener dos valores, 0 y 1. Figura.4
B) SEMAFOROS CON MULTIPLES VARIABLES
Semáforos generales, este tipo de semáforo puede tomar cualquier valor no negativo para
poder hacer su proceso de sincronización siendo cero la condición de ejecución de un proceso
y la espera de otro.
En conclusión, este tipo de semáforo puede tomar distintos valores talvez con la finalidad de
realizar conteos. Figura. 5.1
Puede tomar muchos valores positivos. Figura 5.2
DIFERENCIA
La cantidad de valores que pueden tomar cada una de ellos, los binarios solo tomaran dos y
las múltiples variables podrá tomar cualquier número no negativo con la finalidad de poder
realizar conteos.
12
Su aplicación, los semáforos binarios al tomar solo dos valores son usados cuando solo un
proceso puede acceder a un recurso a la vez, en cambio los semáforos multi variables pueden
usarse para varios procesos y para varios recursos. (Pozo, 2016)
6. VENTAJAS E INCONVENIENTES
(1984.lsi.us.es, 2020)La principal ventaja de los semáforos frente a los cerrojos es que
permiten sincronizar dos o más procesos de manera que no se desperdician recursos de CPU
realizando comprobaciones continuadas de la condición que permite progresar al proceso.
Resuelven todos los problemas que presentan la concurrencia.
Estructuras pasivas muy simples.
Fáciles de comprender.
Tienen implementaciones muy eficientes.
Los inconvenientes asociados al uso de semáforos son los siguientes:
Los programadores tienden a usarlos incorrectamente, de manera que no resuelven de
manera adecuada el problema de concurrencia o dan lugar a interbloqueos.
No hay nada que obligue a los programadores a usarlos. Los compiladores no ofrecen
ningún mecanismo de comprobación sobre el correcto uso de los semáforos.
Son independientes del recurso compartido al que se asocian. Debido a estos
inconvenientes, se desarrollaron los monitores.
Son de muy bajo nivel y un simple olvido o cambio de orden conduce a bloqueos.
Requieren que la gestión de un semáforo se distribuya por todo el código.
La depuración de los errores en su gestión es muy fácil.
7. GRANULARIDAD
Número de recursos controlados por cada semáforo. Hay de dos tipos:
13
Granularidad fina: Un recurso por semáforo. Hay un mayor grado de paralelismo, lo que
puede mejorar la rapidez de ejecución de la protección. Aunque a mayor número de
semáforos existe una mayor probabilidad de que se dé un interbloqueo entre semáforos, que
no sería una mejora de lo que intentamos evitar.
Granularidad gruesa: Un semáforo para todos los recursos. Caso totalmente inverso al
anterior: Ahora al tener un semáforo no se produce interbloqueo entre ellos, aunque los
tiempos de ejecución son excesivamente largos. (1984.lsi.us.es, 2020)
CONCLUSIONES
Los semáforos se emplean para permitir el acceso a diferentes partes de programas
(llamados secciones críticas) donde se manipulan variables o recursos que deben ser
accedidos de forma especial. Según el valor con que son inicializados se permiten a más o
menos procesos utilizar el recurso de forma simultánea.
Un tipo simple de semáforo es el binario, que puede tomar solamente los valores 0 y 1. Se
inicializan en 1 y son usados cuando sólo un proceso puede acceder a un recurso a la vez. Son
esencialmente lo mismo que los mutex. Cuando el recurso está disponible, un proceso accede
y decrementa el valor del semáforo con la operación P. El valor queda entonces en 0, lo que
hace que si otro proceso intenta decrementarlo tenga que esperar. Cuando el proceso que
decrementó el semáforo realiza una operación V, algún proceso que estaba esperando
comienza a utilizar el recurso.
Para hacer que dos procesos se ejecuten en una secuencia predeterminada puede usarse un
semáforo inicializado en 0. El proceso que debe ejecutar primero en la secuencia realiza la
operación V sobre el semáforo antes del código que debe ser ejecutado después del otro
proceso. Este ejecuta la operación P. Si el segundo proceso en la secuencia es programado
para ejecutar antes que el otro, al hacer P dormirá hasta que el primer proceso de la secuencia
pase por su operación V. Este modo de uso se denomina señalación (signaling), y se usa para
que un proceso o hilo de ejecución le haga saber a otro que algo ha sucedido. (Downey, 20 oct
2022)
14
APÉNDICE
Figura 1. Esqueleto de lo que hace el nivel más bajo del sistema operativo cuando ocurre
una interrupción.
15
Figura 2. Diagrama de bloques.
Figura 3. El problema del productor-consumidor mediante el uso de semáforos.
16
Figura 4.
Figura 5.1
17
Figura 5.2
18
19
Figura 6.
20
BIBLIOGRAFÍA
1984.lsi.us.es. (2020). Planificador de procesos: Diagrama de estados simplicado. wiki-ssoo.
Obtenido de https://1984.lsi.us.es/wiki-ssoo/index.php/Sem
%C3%A1foros#:~:text=Los%20sem%C3%A1foros%20son%20un%20mecanismo,de
%20dos%20o%20m%C3%A1s%20procesos.
Downey, A. B. (20 oct 2022). The Little Book of Semaphores. Wikipedia®. Obtenido de
https://es.wikipedia.org/wiki/Sem%C3%A1foro_(inform%C3%A1tica)#Aplicaciones
gadget-info.com. (2019). Diferencia entre Deadlock y Starvation en OS. Obtenido de
https://es.gadget-info.com/difference-between-deadlock
github. (2017). Miangame Cena-de-los-filosofos. Obtenido de
https://github.com/Miangame/Cena-de-los-filosofos-C
NANCY QUINTERO, J., & LOPEZ, E. T. (2011). Semáforos Sistemas Operativos.
blogger.com. Obtenido de http://sistemasoperativo252m.blogspot.com/2011/01/29-
semaforos-sistemas-operativos.html
Pozo, D. (2016). Sistemas Operativos: Semáforos. Obtenido de
https://danielpozoblog.wordpress.com/2016/09/28/sistemas-operativos-semaforos/
TANENBAUM, A. S., & MAARTEN, V. S. (2009). Sistemas operativos modernos - 3ra
edición. México: EARSON EDUCACIÓN.
21