martes, 26 de octubre de 2010

Semaforos y Monitores

Semáforos
Un semáforo es un mecanismo de sincronización que se utiliza generalmente en sistemas de memoria compartida, bien sea un monoprocesador o multiprocesador.Para sincronizar dos o más procesos, de modo que su ejecución se realice de forma ordenada y sin conflictos entre ellos. Su uso en una multicomputadora depende del S.O. en particular.
El por qué no se pueden usar directamente otras estructuras más clásicas, como por ejemplo usar una variable común para decidir si se puede o no acceder a un recurso, se debe a que estamos en un sistema multitarea: hacer esto implicaría realizar una espera activa (un bucle, comprobando constantemente si la variable está o no a 0, y así saber si podemos seguir ejecutando o no). Por otro lado, puede ocurrir algo mucho peor: supongamos que un proceso comprueba la variable, y ve que el recurso está libre, por lo que procedería a cambiar dicha variable de valor y seguir. Pues bien, si justo después de la comprobación pero antes de que cambie el valor se conmuta de tarea (puede pasar, pues el sistema operativo puede hacerlo en cualquier momento), y el nuevo proceso comprueba la variable, como todavía no se ha actualizado, creerá que el recurso está libre, e intentará tomarlo, haciendo que ambos programas fallen. Lo peor del caso es que se tratará de un error aleatorio: unas veces fallará (cuando se produzca cambio de tarea en ese punto) y otras no.
Para evitarlo, se idearon los semáforos que es una estructura formada por una posición de memoria y dos instrucciones, una para reservarlo y otra para liberarlo. A esto se le puede añadir una cola de procesos para recordar el orden en que se hicieron las peticiones.
Un semáforo es un objeto con un valor entero, al que se le puede asignar un valor inicial no negativo y al que solo se puede acceder utilizando 2 operaciones atómicas: Wait y Signal.
La operación wait también recibe otros nombres como down  o P (para espera), la operación signal recibe otros nombres como up o V.
Funcionamiento
Se empieza por inicializar la posición de memoria a 1 (o al valor correspondiente si ese recurso concreto admite más de un acceso simultáneo). Esto se hace en el inicio del programa principal.
A continuación, cada vez que un un proceso quiera acceder a dicho recurso (por ejemplo, un fichero), hará primero una petición con la primera de las llamadas disponibles. Cuando el S.O. ejecuta esa llamada, comprueba el valor que hay en la posición de memoria del semáforo, y si es distinta de cero, se limita a restarle 1 y devolver el control al programa; sin embargo, si ya es cero, duerme al proceso que hizo la petición y lo mete en la cola de procesos, en espera de que el semáforo se ponga a un valor distinto de cero.
Por último, cuando el proceso ha terminado el acceso al recurso, usa la segunda llamada para liberar el semáforo. Cuando el S.O. la ejecuta, comprueba si la cola del semáforo está vacia, en cuyo caso se limita a incrementar el valor del semáforo, mientras que si tiene algún proceso, lo despierta, de modo que vuelve a recibir ciclos de CPU y sigue su ejecución. Si había varios procesos en espera, se irán poniendo en marcha uno tras otro a medida que el anterior va liberando el semáforo. Cuando termina el último, el semáforo se vuelve a poner a 1.
Se trata, por tanto, del mismo proceso que seguiríamos con la variable, pero con la ventaja de que es un mecanismo estándar para todos los procesos, y como es una operacion atómica (esto es, que durante su ejecución no se admiten cambios de tarea), no surge el problema de que una conmutación pueda producir errores aleatorios.

                                                               MONITORES
La construcción de sincronización de alto nivel es  el tipo monitor. Un monitor se caracteriza por un conjunto de operadores definidos por el programador. La representación de un tipo de monitor consiste en declaraciones de variables cuyos valores definen el estado de un ejemplar del tipo, asi como los cuerpos de procedimientos o funciones que implementan operaciones con el tipo.
Un procedimiento definido dentro de un monitor solo puede acceder   a las variables declaradas localmente  dentro del monitor, y a los parámetros formales.
La construcción del monitor garantiza que solo podrá estar activo un proceso a la vez dentro del monitor
Un programador que necesite escribir su propio esquema de sincronización a la media puede definir una o más variables de tipo condición:
Var x,y: condición
Las únicas operaciones que se pueden invocar para una variable de condición son espera y señal.la operación
x.espera;
Significa que el proceso que invoca esta operación se suspenderá hasta que otro proceso invoque
x.señal:
la operación x.señal reanuda uno y solo un proceso suspendido. Si no hay proceso suspendido, la operación señal no tiene ningún efecto; es decir, el estado de x es como si la operación nunca se hubiera ejecutado.  la operación señal asociada a los semáforos , que siempre afecta el estado del semáforo.
Cuando un proceso p invoca la operación x.señal , existe un proceso suspendido q asociado a la condición x. queda claro que , si se permite que el proceso suspendido q reanude su ejecución , el proceso señalizador p deberá esperar ; de lo contrario , tanto p como q estarían activos simultáneamente dentro del monitor . Cave de señalar que conceptualmente ambos procesos pueden continuar con si ejecución. Hay 2 posibilidades.
1: p espera hasta que q sale del monitor o bien espera otra condición
2: q espera hasta que p sale del monitor, o bien espera otra condición