• No se han encontrado resultados

Crear un puerto.

In document Conceptos de Sistemas Operativos (página 49-53)

·

Enviar y recibir mensajes a través de un puerto.

·

Destrozar un puerto.

El proceso que crea un puerto es el propietario del mismo por defecto, y es el único que puede recibir mensajes a través de éste buzón. Sin embargo, la posesión y el privilegio de recibir mensajes puede ser pasada a otro proceso a través de una llamada de sistema. Por supuesto, ésta propiedad podría derivar en múltiples recibidores de un mismo puerto. Los procesos también pueden compartir un puerto a través de la creación de procesos. Por ejemplo, si un proceso P crea el puerto A, y luego crea un nuevo proceso Q, P y Q comparten el buzón.

Buffering: un enlace tiene alguna capacidad que determina el número de mensajes que puede residir en él temporariamente. Esta propiedad puede ser vista como una cola de mensajes unidas al enlace. Básicamente existen tres formas en las cuales puede ser implementada tal cola:

Capacidad cero: la cola tiene un largo máximo de 0; así, el enlace no tiene ningún mensaje

esperando en él. En este caso, el emisor debe esperar hasta que el receptor reciba el mensaje. Los dos procesos deben estar sincronizados para que la transferencia de un mensaje tome lugar.

Capacidad limitada: La cola tiene un largo finito de n; así, como mucho n mensajes pueden

residir en la cola. En caso de que la cola no este llena en el momento que un mensaje es enviado, es ubicado en la cola (ya sea que el mensaje es copiado o se mantiene un puntero al mensaje), y el emisor puede continuar ejecutando sin la necesidad de esperar. Sin embargo, el enlace tiene una capacidad finita, por lo que si el enlace esta lleno, el emisor debe esperar hasta que halla espacio disponible en la cola.

Capacidad ilimitada: La cola tiene un largo infinito; así, pueden esperar en el enlace cualquier

La capacidad cero se refiere a veces a un sistema de mensajes sin buffering; en cambio los otros dos proveen buffering automático.

Notemos que, en los casos donde la capacidad no es cero, el proceso no conoce si un mensaje ha llegado a o no a destino luego de que la operación send fue realizada. Si ésta información es crucial para la computación, el emisor debe comunicarse explícitamente con el receptor para averiguar si el mensaje fue recibido. Por ejemplo, supongamos que el proceso P envía un mensaje al proceso Q y puede continuar su ejecución solo si el mensaje enviado llego a destino. El proceso P ejecutara la secuencia:

send(Q, mensaje) receive(Q, mensaje) El proceso Q ejecutara:

receive(P, mensaje) send(P, “acuse de recibo”)

A tales procesos se dice que están comunicados asincrónicamente.

Hay casos especiales que no entran en ninguna de las categorías que se vieron:

El proceso que envía el mensaje nunca es demorado (es decir, nunca se queda esperando). Sin embargo, si el proceso receptor del mensaje no recibió este primer mensaje antes de que el proceso emisor envíe otro mensaje, entonces el primer mensaje estará perdido. La ventaja de este esquema es que los mensajes grandes no necesitan ser copiados más de una vez. La mayor desventaja es que la tarea de programación es más difícil. Los procesos necesitan una sincronización explícita para estar seguros si el mensaje está o no perdido, y que el emisor y el receptor no manipulen simultáneamente el buffer.

El proceso que envía un mensaje es retrasado hasta que recibe una respuesta. En este sistema, los mensajes son de un tamaño fijo (ocho palabras). Un proceso P que envía un mensaje es bloqueado hasta que el proceso receptor ha recibido el mensaje y envía una respuesta de ocho palabras por medio de la primitiva reply(P, mensaje). El mensaje de respuesta sobreescribe el buffer del mensaje original. La única diferencia entre las primitivas send y reply es que un send causa que el proceso que envía el mensaje sea bloqueado, mientras que reply hace que tanto el proceso emisor y el proceso receptor continúen sus ejecuciones inmediatamente. Este método de comunicación sincrónica se puede extender a un sistema RPC (call procedure remote), el cual esta basado en que una llamado a un procedimiento o subrutina en un sistema de único procesador actúa exactamente como un sistema de mensajes en el cual el emisor se bloquea hasta que reciba una respuesta. Este mensaje es entonces como el llamado a una subrutina, y el mensaje de retorno contiene el valor de la subrutina computada. De esta manera, el siguiente paso lógico es que los procesos concurrentes sean capaces de llamarse entre sí como subrutinas usando RPC.

Condiciones de excepción: Un sistema de mensajes es muy útil en un entorno distribuido, donde los procesos pueden residir en diferentes maquinas. En tales ambientes, la probabilidad de que ocurra un error durante la comunicación (y procesamiento) es mucho más grande que la que existe en un entorno de una única maquina. En una única maquina, los mensajes son usualmente implementados con el método de memoria compartida. En caso de que ocurra un fallo, entonces el sistema entero falla. En un entorno distribuido, sin embargo, los mensajes son transferidos por una línea de comunicación, y la falla de un sitio (o enlace) no necesariamente debe resultar en la falla del sistema completo.

Cuando una falla ocurre en un sistema centralizado o distribuido, toma lugar algunos sistemas de recuperación de errores (excepciones). Veremos brevemente algunas de las condiciones de excepción que el sistema puede manejar en el esquema de mensajes.

El proceso termina: Un emisor o un receptor puede terminar antes de que un mensaje sea procesado. Esta situación provocara la existencia de mensajes que nunca serán recibidos, o procesos esperando por mensajes que nunca serán enviados. Consideremos dos casos:

1. Un proceso receptor P puede esperar por un mensaje del proceso Q que ha terminado. Si no es tomada ninguna acción, P estará bloqueado por siempre. En este caso, puede optar por terminar también P o avisarle a P que Q ha terminado.

2. El proceso P puede enviar un mensaje a Q que ha terminado. En el esquema de buffering automático no se produce daño: P simplemente continúa con su ejecución. En caso de que P necesite saber si el mensaje fue procesado por Q, éste debe explícitamente programar por un acuse de recibo. En el caso de que no halla buffering, P será bloqueado por siempre. Como en el caso 1, el sistema puede optar por terminar P o notificar a P que Q ha terminado.

Perdida de mensajes: Un mensaje desde el proceso P al proceso Q se puede perder en algún

lugar de la comunicación de red, falla del hardware, o falla en la línea de comunicación. Hay tres métodos básicos para tratar con este evento:

1. El sistema operativo es el responsable de detectar éste evento y de retransmitir el mensaje.

2. El proceso emisor es el responsable de detectar éste evento y de retransmitir el mensaje, en caso de que quiera hacerlo.

3. El sistema operativo es el responsable de detectar éste evento; éste entonces notifica al proceso emisor que el mensaje se ha perdido. El proceso emisor puede elegir lo que le convenga.

La pérdida de un mensaje se puede detectar por medio del uso de timeouts. Cuando un mensaje es enviado siempre retorna un mensaje de respuesta o un acuse de recibo. El sistema operativo o el proceso puede especificar un intervalo de tiempo en el cual éste espera que llegue el mensaje de acuse de recibo. En caso de que éste periodo de tiempo termine antes de que llegue el mensaje de acuse de recibo, el sistema operativo (o el proceso) puede asumir que el mensaje se perdió, y que el mensaje será reenviado. Puede ocurrir sin embargo que el mensaje no se perdió sino que el mensaje de acuse tardo más en llegar que el tiempo en el cual esta determinado el timeout. En este caso, se pueden obtener múltiples copias del mismo mensaje. Ante esto, debe existir un mecanismo para distinguir entre los diferentes tipos de mensajes.

Un ejemplo: Mach. Como ejemplo de un sistema operativo basado en pasaje de mensajes, consideremos el sistema operativo Mach. El kernel del Mach soporta la creación y destrucción de múltiples tareas, las cuales son similares a los procesos pero tiene múltiples threads de control. La mayor parte de la comunicación en Mach, incluyendo la mayoría de las llamadas la sistema y toda la información entre tareas, es llevada a cabo por mensajes. Los mensajes son enviados y recibidos por casillas llamadas puertos (en la nomenclatura Mach).

Las llamadas al sistema son hechas vía mensajes. Cuando se crea una tarea, también se crean dos puertos: el puerto del kernel y el puerto de Notificación. El puerto del kernel lo usa el kernel para comunicarse con la tarea. El kernel envía la notificación de los eventos que ocurren al puerto de Notificación. Solo se necesitan tres llamadas al sistema para la transferencia del mensaje. La llamada msg_send envía un mensaje al puerto. Un mensaje es recibido vía msg_receive. Los llamados a procedimientos remotos (RPC) son ejecutados vía msg_rpc, el cual envía un mensaje y espera por un mensaje de retorno del emisor. La llamada al sistema port_allocate crea un nuevo puerto y asigna espacio para su cola de mensajes. El tamaño máximo de la cola de mensajes por defecto es de 8 mensajes. La tarea que crea el puerto es la dueña del puerto.

Al inicio, el puerto esta vacío de mensajes. A medida que los mensajes son enviados al puerto, estos se copian en él. Todos los mensajes tienen la misma prioridad. Mach garantiza que los múltiples mensajes enviados por un mismo emisor son encolados en una orden de tipo FIFO, pero no garantiza un orden absoluto. Por ejemplo, los mensajes enviados por diferentes emisores se pueden ordenar de cualquier manera.

Las operaciones del emisor y el receptor son bastante fáciles. Por ejemplo, cuando se envía un mensaje al puerto, el puerto puede estar lleno. Si el puerto no esta lleno, el mensaje se copia en el puerto y el thread emisor continúa. Si el puerto esta lleno, el thread emisor tiene cuatro opciones:

Esperar indefinidamente hasta que haya lugar en el puerto. Esperar a lo sumo n milisegundos.

No esperar, sino retornar inmediatamente.

Guardar el mensaje temporariamente en cache. Un mensaje se le puede dar al sistema operativo ya que el puerto de destino esta lleno. Cuando el mensaje ya tiene lugar, se le envía un mensaje al emisor.

Un ejemplo: Windows NT. El sistema operativo Windows NT es un ejemplo de diseño moderno de un sistema que emplea la modularidad para incrementar la funcionalidad y disminuir el tiempo empleado para agregar nuevas características. NT provee soporte para diferentes sistemas operativos o subsistemas con programas de aplicación que se comunican con un mecanismo de paso de mensajes. Los programas de aplicación pueden ser considerados como clientes del servidor de NT.

La facultad de paso de mensajes en NT es llamada Local Procedure Call (LPC). El LPC en NT se usa para comunicar dos procesos que están en la misma maquina. NT, así como Mach, usa objetos puerto para establecer y mantener la comunicación entre dos procesos. Cada cliente que llama a un subsistema necesita un canal de comunicación el cual es proveído por un puerto y nunca es heredado. Existen dos tipos de puertos en NT: los puertos de conexión y los puertos de comunicación, el cual en realidad son los mismos pero difieren en su nombre de acuerdo el uso que se les da.

5. Scheduling de CPU

El scheduling de la CPU es lo básico de los sistemas operativos multiprogramados. Por medio del cambio de la CPU entre los diferentes procesos, el sistema operativo puede hacer que la computadora funcione de manera más eficiente.

In document Conceptos de Sistemas Operativos (página 49-53)