LICENCIATURA EN SISTEMAS DE INFORMACIÓN

 

 

 

 

 

SISTEMAS OPERATIVOS

 

 

 

 

 

 

 

 

MONOGRAFÍA GRUPO Nº 1

TEMA:

SOPORTE DEL SISTEMA OPERATIVO

 

 

 

 

 

 

 

 

Alumnos integrantes:

 

¨              Barrios Mayra                                                          L.U. Nº 34.102

¨              Cemborain Juan Martín                                        L.U. Nº 34.079

¨              Zamparo Fabio                                                        L.U. Nº 33.708

¨              Altamirano Romina                                                L.U. Nº 33.109

¨              Billordo Rosa Adriana                                           L.U. Nº 32.701

¨              Valenzuela Juan Alberto                                       L.U. Nº 31.003

¨              Montenegro Carmenia                                           L.U. Nº 30.658

¨              De los Reyes Leonardo                                           L.U. Nº 30.279

¨              Acosta Germán                                                         L.U. Nº 30.011

¨              Leguisamón Miguel Adolfo                                  L.U. Nº 29.209

¨              Cemborain Guillermo                                             L.U. Nº 26.913

 

 

 

 

 

 


ÍNDICE

 

ü       Nivel del Sistema Operativo

ü       Protección

ü       Procesos e Hilos

ü       Creación de un proceso nuevo

ü       Hilos

ü            Arquitecturas para servidores multi-hilo

 

ü       Hilos dentro de los clientes

ü       Programación de hilos

ü       Tiempos de vida de los hilos

ü       Sincronización de hilos

ü       Planificación de hilos

ü       Comunicación e invocación

ü            Primitivas de sincronización

ü            Protocolos y apertura

ü       Prestaciones de la invocación

ü       Elección del protocolo

ü       Operación Asíncrona

ü       Arquitectura del Sistema Operativo

ü       Comparación

ü       Algunas aproximaciones híbridas


Middlewere y Sistemas Operativos en Red.

 

En realidad, no se emplea ningún sistema operativo distribuido, sino solo sistemas operativos en red del tipo de UNÍX, MacOS y diferentes variantes de  Windows.

Esta situación tiende a mantenerse, por dos razones:

 

     La primera es que los usuarios ya han realizados grandes inversiones en su software de aplicación, que normalmente resuelve sus problemas; por lo que no cambiaran a un nuevo sistema operativo que es incapaz de ejecutar sus aplicaciones, por muchas ventajas que ofrezca.

     La segunda razón en contra, es que los usuarios prefieren tener autonomía en la gestión de sus propias máquinas, incluso en organizaciones fuertemente cohesionadas, para conseguir buenas prestaciones.

 

La combinación de middlewere y sistema operativo en red proporciona un equilibrio aceptable entre los requisitos de autonomía, por un lado, y la transparencia de red en el acceso a recursos, por el otro.

¨       Los sistemas operativos en red permiten a los usuarios ejecutar su procesador de textos junto con otro tipo de aplicaciones (independiente).

¨       El middlewere les permite acceder a los servicios que aparecen como disponibles en el sistema distribuido.

 

El Nivel de Sistema Operativo.

 

El middlewere se ejecuta en múltiples combinaciones hardware/ sistema operativo, es decir, en múltiples plataformas en los nodos de un sistema distribuido. El sistema operativo que se ejecuta en un cierto nodo (un núcleo junto con los servicios asociados de nivel de usuario, por ej., bibliotecas) proporciona dentro de ese nodo su propia imagen sobre las abstracciones de los recursos hardware locales de procesamiento, de almacenamiento y de comunicación.

El middlewere utiliza una combinación de esos recursos locales para implementar los mecanismos de invocación remota entre objetos o procesos en los nodos.  

Cuadro de texto: OS: núcleo, biblioteca y servidores
 


Middlewere

 

Aplicaciones, servicios

 

Computador y hardware de red

 

OS1

Procesos, hilos, comunicaciones,...

 

 

OS2

Procesos, hilos, comunicaciones,...

 

 

Computador y hardware de red

 
Cuadro de texto: Plataforma

                                                 


                           

           Nodo 1                                         Nodo2

 

                                             Niveles del sistema

 

La figura, muestra cómo el nivel de sistema operativo en cada uno de los dos nodos soporta un nivel de middlewere común para proporcionar una infraestructura distribuida para aplicaciones y servicios.

Los núcleos y los procesos cliente y servidor que se ejecutan son los principales componentes de la arquitectura sobre los que trataremos.

Los núcleos y el proceso servidor son los componentes que gestionan los recursos y los presentan a los clientes a través de una interfaz de recursos. Esta debe tener las siguientes características:

R     Encapsulamiento: debe proporcionar un servicio de interfaz útil sobre los recursos, conjunto de operaciones que cubra las necesidades. Los detalles del tipo gestión de la memoria o dispositivos utilizados para implementar los recursos deben ocultarse a los clientes.

R     Protección: los recursos deben protegerse de los accesos no permitidos.

R     Procesamiento concurrente: los clientes pueden compartir múltiples recursos y acceder a ellos concurrentemente. Los gestores de recursos son los responsables de conseguir transparencia en la concurrencia.

Los clientes acceden a los recursos mediante, por ejemplo, invocaciones a un método remoto de un objeto que reside en un cierto servidor o bien mediante llamadas al sistema en el núcleo. Los mecanismos de acceso a un recurso encapsulado se denominan mecanismo de invocación. Una combinación de bibliotecas, núcleos y servidores puede utilizarse para realizar las siguientes tareas de invocación:

  

R     Comunicación: los parámetros de operación y los resultados deben pasarse hacia y desde los gestores de recursos, utilizando una red o bien dentro del computador.

R     Planificación: cuando se invoca una cierta operación, su procesamiento debe planificarse dentro del núcleo o del servidor.


 


                                   Funcionalidad básica del sistema operativo

 

La figura muestra la funcionalidad básica del sistema operativo la cual está relacionada con. La gestión de procesos e hilos, la gestión de la memoria, y la comunicación entre procesos en el mismo computador (las divisiones horizontales indican dependencia). El núcleo proporciona gran parte de esta funcionalidad.

El software del S.O. se diseña para ser portable entre las diferentes arquitecturas de computadores, se codifica en e un lenguaje de alto nivel, ya sea C, C++ o Modula-3, y que sus servicios se organizan por niveles de forma que los componentes dependientes de la máquina se reducen a un único nivel inferior.

Multiprocesadores de memoria compartida

 

Los computadores multiprocesador de memoria compartida se componen de varios procesadores que comparten uno o más módulos de memoria (RAM). Los procesadores pueden tener también su propia memoria privada. Se pueden construir de diferentes formas:

 

# Los más simples y menos costosos están construidos incorporando una tarjeta que contiene de 2 a 8 procesadores en un computador personal.

 

Los multiprocesadores en los sistemas distribuidos son particularmente muy utilizados para la implementación de servidores de alta prestaciones ya que el servidor puede ejecutar un único programa con varios hilos los cuales gestionan varias solicitudes llegadas de diferentes clientes de forma simultánea.  

 

Los principales componentes de un sistema operativo son los siguientes:

     Gestor de procesos: gestiona la creación y las diferentes operaciones sobre procesos (unidad de gestión de recursos que incluye un espacio de direcciones y uno o más hilos).

     Gestor de hilos: incluye la creación, sincronización y planificación de hilos (son actividades planificables asociadas a procesos).

     Gestor de las comunicaciones: comunicaciones entre hilos asociados a diferentes procesos en un mismo computador. Algunos núcleos soportan comunicación entre hilos asociados a procesos remotos. Otros no, de forma que deben añadirse servicios adicionales para las comunicaciones externas.

     Gestor de memoria: gestión de memoria física y virtual.

     Supervisor: se ocupa de la resolución de interrupciones, interrupciones internas de llamadas al sistema y otras, control de la unidad de gestión de memoria y de las ante memoria (caché) hardware; manipulación de registros del procesador y la unidad en punto flotante. A todo esto se llama Nivel de Abstracción del hardware en Windows NT.

 

 

Protección:

 

 Los recursos necesitan protección contra los accesos no permitidos. Hay que tener en cuenta que las amenazas a la integridad de un sistema no previenen únicamente de código ideado de forma maliciosa. También un código bien intencionado puede contener un error o puede tener un comportamiento no esperado, provocando que parte del sistema se comporte a su vez de forma incorrecta.

 Para comprender lo que se quiere decir con acceso ilegitimo a un recurso, consideremos un archivo abierto para lectura y escritura. La protección del archivo se puede descomponer en dos sub-problemas. El primero consiste a asegurar que cada una de las dos operaciones sobre el archivo solo puede ser realizada por clientes. Por ejemplo Gonzáles, que es el propietario del archivo, tiene los derechos de lectura y escritura sobre el. Pérez solo necesita acceder a la operación de lectura. En este caso se producirá un acceso ilegitimo si Pérez intentara realizar una operación de escritura sobre el archivo.

 El otro tipo de acceso ilegitimo, ocurre cuando un proceso se comporta de forma errónea, esquivando operaciones que se exportan sobre un recurso. En nuestro ejemplo esto ocurriría si Gonzáles o Pérez, de alguna forma, ejecutaran una operación que no fuera lectura o escritura.

 Podemos proteger, los recursos, de invocaciones ilegitimas del tipo SET FILE POINT ERRAND ONLY.

 Una posibilidad insiste en utilizar un lenguaje de programación con sistema de tipos seguro como Java o Modula-3. Estos lenguajes no permiten que un modulo acceda a otro modulo objeto a no ser que previamente obtenga una referencia a este ultimo. Por el contrario, en C++ un programador puede realizar asignaciones a un puntero a voluntad, realizando de esta forma invocaciones de tipo inseguras

 

PROCESOS E HILOS

 

El concepto tradicional en los sistemas operativos de que un proceso ejecuta una única actividad, ya se comprobó, en la década de los ochenta, que era poco adecuado para las especificaciones de los sistemas distribuidos; y también para ciertas aplicaciones sobre un solo computador que necesitan concurrencia interna. El problema es que los procesos realizan la comparición  entre actividades relacionadas de una forma difícil y cara.

La solución consistió en  ampliar el concepto de proceso de forma que pudiera asociarse a múltiples actividades. En la actualidad un proceso consiste en un entorno de ejecución formado por uno o más hilos. Un hilo es una abstracción del sistema operativo asociada a una actividad. Un Entorno de ejecución equivale a una unidad de gestión de recursos: una colección de recursos locales gestionados por el núcleo sobre los que tienen acceso los hilos.

 

Un entorno de ejecución consiste básicamente de los siguientes elementos:

 

-         Un espacio de direcciones

-         Recursos de comunicación y sincronización de hilos, como semáforos e interfaces de comunicación.

-         Recursos de alto nivel, como archivos abiertos y ventanas.

 

Los entornos de ejecución son caros en cuanto a su creación y gestión, aunque sin embargo pueden ser compartidos por más de un hilo, es decir, estos pueden compartir todos los recursos accesibles dentro de cada entorno. Entonces, un entorno de ejecución representa el dominio de protección en el que se ejecutan los hilos.

 

Los hilos pueden crearse y destruirse en forma dinámica. El principal propósito para la existencia de múltiples hilos es maximizar el grado de ejecución concurrente entre las diferentes operaciones, permitiendo así habilitar el solapamiento de la computación con la entrada- salida y el procesamiento concurrente en los multiprocesadores. Esto es particularmente útil  en los servidores en los que el procesamiento concurrente de las solicitudes de los clientes pueden reducir la tendencia de los servidores a  convertirse en cuellos de botella.

 

Un entorno de ejecución proporciona protección contra los hilos externos de forma que los datos y otros recursos contenidos en el sean inaccesibles para los hilos residentes en otros entornos de ejecución. Sin embargo ciertos núcleos permiten compartir en forma controlada recursos entre entornos de ejecución diferentes residentes en el mismo computador.

 

ESPACIOS DE DIRECCIONES

 

Es una unidad de gestión de memoria virtual de un proceso. Es grande y esta formado por una o mas regiones, separadas por áreas de memoria virtual inaccesibles.

Una región es una zona de memoria virtual contigua accesible por los hilos del proceso propietario. Las regiones no se solapan. Hay que resaltar la distinción entre regiones y sus contenidos. Cada región se caracteriza por las siguientes propiedades:

 

-         Su tamaño

-         Los permisos de lectura/ escritura/ ejecución para los hilos del proceso.

-         Una indicación de crecimiento hacia arriba o hacia abajo.

 

Este modelo esta orientado a páginas. Las regiones podrían eventualmente solaparse si su tamaño se extendiera. Entre las regiones se dejan huecos para permitir  su crecimiento. Esta representación de un espacio de direcciones como un conjunto disperso de regiones disjuntas es una generalización del espacio de direcciones de UNÍX, el cual esta formado por tres regiones: una región de texto de tamaño fijo y no modificable, que contiene el código del programa; un montón (heap), parte del cual se inicializa con los valores almacenados en el archivo binario con el programa, y que es ampliable hacia direcciones virtuales crecientes; y una pila, que crecerá hacia direcciones virtuales decrecientes.

 

La existencia de un número determinado de regiones tiene su razón de ser en varios factores. Uno de ellos es la necesidad de que haya pilas separadas para cada hilo. La existencia de regiones de pila distintas para cada hilo permite detectar los intentos de exceder el límite de la pila y controlar el crecimiento de cada una de ellas. La memoria virtual no utilizase halla debajo de cada región de pila y los intentos de acceder a esa región generan excepciones. Una alternativa consiste en asignar la pila de cada hilo en el montón, sin embargo en este caso ase hace difícil detectar cuando un hilo excede el limite de su pila.

La necesidad de compartir memoria entre procesos, o entre procesos y núcleo, es otro factor que deriva en la necesidad de regiones adicionales en el espacio de direcciones. Una región de memoria compartida es aquella en la que se asocia la misma memoria física a una o más regiones pertenecientes a otros espacios de direcciones. Por lo tanto los procesos acceden  a los mismos contenidos de memoria en las regiones compartidas mientras que sus regiones no compartidas permanecen protegidas. Algunos usos de las regiones compartidas son las siguientes:

 

-         bibliotecas: el código de las bibliotecas puede llegar a ser muy grande y se desperdiciaría una cantidad considerable de memoria si se cargaran de forma separada en cada proceso que las utilizase. Por el contrario, varios procesos pueden compartir una sola copia del código de las bibliotecas empleando una región compartida del espacio de direcciones.

-         Núcleo: frecuentemente el código y los datos de los núcleos corresponden dentro del espacio de direcciones en las mismas posiciones. Cuando un proceso realice una llamada al sistema, o bien cuando se genere una excepción, no habrá necesidad de conmutar a un nuevo conjunto de direcciones.

-         Compartir datos y comunicación: entre dos procesos, o bien entre un proceso y el núcleo, se puede necesitar compartir datos para cooperar en la realización de cierta tarea. Es más eficiente utilizar regiones de direcciones compartidas en lugar de intercambiar los datos mediante mensaje.

 

Creación de un proceso Nuevo

 

Para un sistema distribuido el diseño de mecanismo de creación de un proceso debe tener en cuenta la utilización de múltiples computadoras, de esta forma la infraestructura de gestión de procesos se divide en servicios de sistemas separados.

 

La creación de un proceso nuevo pude separarse en dos aspectos:

 

La elección del computador destino: el nodo puede elegirse entre varios de un grupo de computadoras que actúan como servidores, la elección del nodo donde residirá el nuevo proceso es una cuestión política, los cuales se distinguen las siguientes categorías de políticas para compartir el uso de la carga.

 

    • Política de transferencia: decide si un proceso nuevo debe ubicarse en el nodo local o en el remoto.
    • Política de ubicación: determina que nodos alojara un proceso nuevo seleccionado para transferir.

 

A su vez estas políticas pueden ser estáticas o adaptativos, los primeros operan sin tener una consideración del estado actual del sistema, se basaron en análisis matemáticos orientados a la optimización de ciertos parámetros, mientras que los segundos aplican reglas heurísticas para tomar las decisiones de ubicación basándose en factores de tiempo de ejecución no predecibles.

 

Los sistemas para compartir la carga pueden ser centralizados, jerárquicos o descentralizados. En el primer caso existe un gestor de carga, en el segundo existen varios.

 

En un sistema de uso compartido de carga descentralizado los nodos intercambian información entre ellos directamente para tomar las decisiones de localización.

 

En los algoritmos de uso compartido de la carga iniciados por el emisor el nodo que solicita la creación del proceso es responsable de iniciar la decisión de transferencia, en cambio en lo que son iniciados por el receptor un nodo cuya carga esta por debajo  de cierto umbral advierte sobre su existencia  a otros nodos con cargas relativamente altas para que inicien las transferencia.

 

El otro aspecto que hay que tener encuentra en la creación de un proceso nuevo es la creación de su entorno. Este esta formado por un espacio de direcciones iniciados con una serie de contenidos. Existen dos aproximaciones en las definiciones del espacio de direcciones, una forma seria con un formato definirlo de forma estáticamente o bien definirlo respecto de un entorno de ejecución existente, en cuyo caso cada región del proceso puede ser heredado  por el de su hijo.

 

Una región heredada puede, o bien ser compartida, o copiarse desde la región del padre. En el primer caso los marcos de páginas pertenecientes a la región del padre concuerdan simultáneamente con las correspondientes del hijo.

 

En el segundo caso, la región es copiada por defecto, no se realiza copia física. Los marcos de página que componen la región heredada se comparten entre los dos espacios de direcciones. Una página  de la región es copiada físicamente únicamente cuando uno de los dos procesos intente modificarla.

 

HILOS

 

Es un aspecto importante de los procesos, debido, entre otras cuestiones, porque define la productividad máxima del servidor medida en solicitudes de cliente manejadas por segundo.

Este número estará en función del número de hilos que el servidor disponga.

 

Por ejemplo, supongamos que en un computador servidor con un solo procesador cada solicitud de cliente necesita 2 mlseg. de proceso y 8 mlseg. de entrada-salida sin caché a disco.

 

Si solo dispone de un hilo para realizar todo el proceso, el tiempo de retorno para una solicitud es 2+8 = 10  mlseg. promedio, o sea que puede atender a 100 clientes/seg. Cualquier mensaje de solicitud que llegue mientras el servidor está manejando una solicitud es insertado en la cola del puerto del servidor.

 

Si en cambio dispone de dos hilos que se manejen en forma independiente, es decir, cada uno se puede planificar cuando el otro pasa a estado bloqueado por operaciones de E/S, se incrementa la productividad del servidor. Si todas las solicitudes al disco se envían en serie a 8 mlseg. por proceso, la productividad es 1.000/8 = 125 solicitudes/seg.

 

Si agregamos la existencia de una caché de disco, el servidor mantiene los bloques leídos en búfferes dentro de su espacio de direcciones; el hilo encargado de obtener datos examina previamente la caché compartida evitándose el acceso a disco si los datos están allí. Considerando una tasa de aciertos del 75%, el tiempo de E/S por solicitud se reduce a 2 mlseg., incrementándose la productividad teórica a 500 solicitudes/seg. Considerando que el tiempo de uso del procesador se incrementa 2,5 mlseg. por búsquedas de datos en la caché, el procesador puede gestionar 1.000/2,5 = 400 solic/seg.

 

La productividad se puede incrementar por medio del uso de multiprocesadores de memoria compartida con múltiples hilos planificados para procesadores múltiples.

 

Si el servidor del ejemplo anterior se ejecuta en un multiprocesador con dos procesadores, con hilos planificados independientemente sobre los procesadores, se podrán procesar solicitudes en paralelo hasta un máximo de dos hilos. La productividad aumenta en este caso a 444 solic/seg.

 

Arquitecturas para servidores multi-hilo

 

Para vincular solicitudes a hilos en un servidor se resume un informe de Schmidt de 1.998, describiendo las arquitecturas basadas en hilos de diferentes implementaciones del Agente de Solicitud de Objetos de CORBA llamado ORB, Object Request Broker.

Cada ORB procesa solicitudes que llegan a través de un conjunto de sockets activos.

(La figura muestra una de las posibles arquitecturas basadas en hilos, la Arquitectura de Asociación de Trabajadores).

En la Arquitectura de Asociación de Trabajadores, en su forma más simple, el servidor durante la inicialización, crea un conjunto fijo de hilos de trabajadores para procesar solicitudes.

El módulo receptor y gestor de cola se implementa normalmente como un hilo de E/S que recibe solicitudes de un grupo de sockets o puertos y las sitúa en una cola para ser recuperadas por los trabajadores. Puede que en ciertos casos sea necesario manejar jerarquía de solicitudes, por ejemplo según el cliente que envíe la solicitud. Esto se puede gestionar mediante múltiples colas, de forma que el trabajador pueda examinar las colas en orden de prioridad.

Las desventajas de esta arquitectura son su escasa flexibilidad y el alto nivel de conmutaciones entre la E/S  y los hilos de trabajo al manejar la cola compartida.

En la Arquitectura de Hilo-por-Solicitud, el hilo de E/S genera un nuevo hilo de trabajo para cada solicitud y ese trabajador se elimina a sí mismo cuando ha procesado la solicitud asociada a un objeto remoto. Esta arquitectura tiene la ventaja de que los hilos no compiten por acceder a una cola compartida y la productividad se maximiza dado que el hilo de E/S puede generar tantos trabajadores como solicitudes tenga. Su desventaja es la sobrecarga debido a las operaciones de creación y destrucción de hilos.

La Arquitectura de Hilo-por-Conexión asocia un hilo por conexión. El servidor crea un hilo trabajador cuando un cliente realiza una conexión y lo destruye cuando se cierra la misma. En el intervalo, el cliente puede realizar múltiples solicitudes sobre la conexión, cuyos destinos pueden ser uno o más objetos remotos.

La Arquitectura de Hilo-por-Objeto asocia un hilo a cada objeto remoto. Un hilo de E/S recibe las solicitudes y las inserta en las colas para los trabajadores, con la diferencia de que en este caso existe una cola por cada objeto.

En cada una de las dos últimas arquitecturas el servidor se beneficia de pequeñas sobrecargas en la gestión de hilos en comparación con la de hilo-por-solicitud.

 

HILOS DENTRO DE LOS CLIENTES

 

Los hilos pueden ser tan útiles para los clientes como para los servidores.  Proceso cliente con dos hilos: el primer hilo genera resultados que se van a enviar al servidor mediante una invocación a método remoto, no necesitando, sin embargo una respuesta. Las invocaciones a métodos remotos normalmente bloquean al que invoca, incluso aunque no sea estrictamente preciso esperar. Este proceso cliente puede añadir un segundo hilo, el cual realiza las invocaciones a los métodos remotos y se bloque mientras el primer hilo puede continuar computando nuevos resultados. El primer hilo deposita sus resultados en búferes que son vaciados por el segundo hilo. Únicamente se bloquea cuando todos los búferes estén llenos.

La cuestión de clientes multihilo es evidente también en el ejemplo de los navegadores Web. El usuario sufre retardos significativos mientras se cargan las paginas; es por lo tanto esencial para los navegadores la gestión de múltiples solicitudes concurrentes a paginas Web.

 

 

HILOS FRENTE A MULTIPLES PROCESOS

 

La utilidad de los hilos permite que la computación se solape con la entrada-salida y, para el caso de un multiprocesador, con otros cómputos. Se puede obtener el mismo solapamiento mediante la utilización de múltiples procesos mono-hilo. La razón por la cual se prefiere el proceso multihilo es: la creación y gestión de los hilos es mas barata que la de procesos  y la de uso compartido de recursos se puede conseguir de forma más eficiente entre hilos que entre procesos ya que los hilos comparten entornos de ejecución.

 

Algunos de los principales componentes del estado que deben gestionarse para entornos de ejecución e hilos: un entorno de ejecución tiene un espacio de direcciones, interfaces de comunicación, recu7rsos de alto nivel del tipo de archivos abiertos y objetos para la sincronización de hilos como los semáforos; además debe mantener una relación de los hilos que se asocian a dicho entorno. Un hilo tiene una prioridad de planificación, un estado de ejecución (como bloqueado o preparado), los valores almacenados correspondientes a los registros del procesador cuando el hilo esta bloqueado y el estado relacionado con la gestión de interrupciones software del hilo. Una interrupción software es un evento que provoca la interrupción del hilo. Si el hilo tiene asignado un procedimiento de gestión se le transfiere el control. Las señales en UNÍS son ejemplos de interrupciones software.

 

El entorno de ejecución y los hilos se asocian con páginas que pertenecen al espacio de direcciones mantenido en memoria principal, mientras que los datos e instrucciones se almacenan en el caché hardware.

 

Comparación entre procesos e hilos:

 

-         la creación de un nuevo hilo dentro de un proceso existente es mas barata que la creación de un proceso.

-         La conmutación a hilo diferente dentro del mismo proceso es mas barata que la conmutación entre hilos de diferentes procesos.

-         Los hilos dentro de un proceso pueden compartir datos y otros recursos de forma más adecuada y eficiente que con procesos separados.

-         Sin embargo, los hilos dentro de un proceso no están protegidos entre ellos.

 

Considérese el coste de creación de un nuevo hilo dentro de un entorno de ejecución existente. La principal tarea consiste en asignar una región para la pila y proporcionar los valores iniciales de los registros del procesador y de al prioridad  y estado de ejecución del hilo. Debido a la existencia de un entorno de ejecución solo se debe colocar un identificador para el en el registro que describe al hilo. La sobrecarga asociada a la creación de un proceso es considerablemente mayor que la asociada a la creación de un nuevo hilo. Es preciso crear en primer lugar un entorno de ejecución, incluyendo las tablas del espacio de direcciones. Anderson  y otro citan valores alrededor de 11 milisegundos para la creación de un proceso UNÍS y sobre 1 milisegundo para la creación de un hilo sobre la misma arquitectura de procesador CVAX ejecutando un núcleo Topaz; en cada caso el tiempo medido supone que la entidad creada realiza exclusivamente una invocación a un procedimiento vacío antes de terminar.

 

Cuando la nueva entidad realiza una tarea significativa en lugar de la invocación al procedimiento nulo, se producen costes a largo plazo que tienden a ser mayores para un nuevo proceso que para un nuevo hilo dentro de un proceso ya existente. En un núcleo que soporte memoria virtual, el nuevo proceso generara faltas de páginas según vaya  accediendo por primera vez a datos e instrucciones. Por otro lado para el caso de la ejecución de un hilo las sobrecargas a largo plazo también pueden ocurrir, pero tienden a ser menores. Cuando el hilo accede al código y a los datos que han sido utilizados recientemente por otros hilos del mismo proceso, automáticamente se aprovecha del hecho de que dichos datos ya residen en cada caché hardware  o bien en la memoria principal.

 

La segunda ventaja de prestaciones de los hilos se refiere a la conmutación entre hilos, es decir la sustitución de un hilo por otro en un cierto procesador. Esto puede generarse varias veces durante la vida del hilo. La conmutación entre hilos que comparten el mismo entorno de ejecución es mas barata que la de los hilos que pertenecen a diferentes  procesos. Las sobrecargas asociadas a la conmutación de hilos corresponden a la planificación y al cambio de contexto.

 

Un contexto de procesador esta formado por los valores de los registros del procesador como el contador del programa y el dominio de protección actual del hardware: el espacio de direcciones y el modo de protección del procesador. El cambio de contexto es la transición entre contextos que ocurre cuando se conmuta entre hilos o cuando un único hilo realiza una llamada al sistema o genera otro tipo de excepción. Supone realizar las siguientes tareas:

 

-         almacenamiento del registro de estado original del procesador y carga del nuevo estado.

-         En algunas situaciones se realiza una transferencia a un nuevo dominio de protección: a esto se lo llama transición de dominio

 

La conmutación al núcleo o a otro hilo que pertenece al mismo entorno de ejecución a través del núcleo, supone la realización de una transición de dominio. El coste es así mayor aunque, si el núcleo esta vinculado al espacio de direcciones del cliente, es aun relativamente bajo. Cuando se conmuta entre hilos que pertenecen a diferentes entornos de ejecución se generan mayores sobrecargas. Los costes a largo plazo debidos a la ocupación de las entradas del caché hardware y de las páginas de memoria principal tienden a aplicarse cuando ocurre la mencionada transición de dominio. Los valores presentados por Anderson  y otros son de 1.8 milisegundos para realizar una conmutación entre procesos UNÍS y de 0.4 milisegundos para la conmutación entre hilos pertenecientes al mismo entorno de ejecución realizada en el núcleo Topaz.

 

Del proceso clientes con dos hilos, el primer hilo genera los datos y se los pasa al segundo hilo el cual genera una invocación a un método remoto o bien una llamada a procedimiento remoto. Ambos hilos pueden acceder a datos a través de variables compartidas. La ventaja esta en la comodidad y eficiencia del uso compartido de datos. Los hilos que comparten un espacio de direcciones y que no han sido codificados en un lenguaje de tipos seguros no están protegidos entre ellos. Un hilo erróneo puede modificar de forma arbitraria los datos de otro hilo, provocando que este falle. Si se requiere protección, o bien se utiliza un lenguaje de tipos seguro o bien es preferible utilizar múltiples procesos en lugar de múltiples hilos.

 

Programación de hilos

La programación de hilos equivale a la programación concurrente, tal y como ha sido estudiada tradicionalmente, por ejemplo, en el ámbito de los sistemas operativos. La mayor parte de la programación de hilos se realiza en lenguajes de programación convencionales como C aumentados con bibliotecas de hilos. Un ejemplo es el paquete de Hilos para C (C Threads) desarrollado para el sistema operativo Mach. Algunos lenguajes proporcionan un soporte directo para hilos, como Ada95, Modula-3 y, de forma más reciente, Java (Oaks y Wong 1999). A continuación explicaremos someramente los hilos de Java.

De la misma forma que en cualquier implementación de hilos, Java proporciona métodos para la creación, destrucción y sincronización de hilos. La clase de Java Thread incluye el constructor y los métodos de gestión mostrados en la Figura 6.8. Los métodos de sincronización Thready Object están en la Figura 6.9.

thread.join(int milisegundos)

            Bloquea el hilo invocador durante el tiempo especificado hasta que el hilo        haya terminado.

 

thread.interrup()

            Interrumpe el hilo: le obliga a volver desde una llamada a método        bloqueante como sleep().

 

objet.wait(long milisegundos, int nanosegundos)

            Bloquea el hilo invocador hasta que una llamada realizada a notify() o notifyAll() en el objeto despierte el hilo, o bien el hilo sea interrumpido, o        bien el tiempo especificado sa haya cumplido.

 

objet.notify(), objet.notifyAll()

            Despierta, respectivamente, uno o todos los hilos que han invocado a wait()    en el objeto.

 

Métodos constructor y de gestión hilos en Java.

Sincronización de hilos

Cuando tenemos varios hilos, muchas veces deseamos que éstos pueden compartir datos, por lo tanto, es indispensable saber sincronizar sus actividades.

En muchas situaciones, hilos que se ejecutan concurrentemente comparten información y deben considerar el estado de las actividades de los demás hilos. Un modelo muy común de tales conjuntos de hilos es conocido como escenarios de productor/consumidor, donde el productor genera un flujo de datos que es consumido por un consumidor.

La programación de un proceso multi-hilo debe realizarse de forma cuidadosa. La principal dificultad consiste en el uso compartido de objetos y en las técnicas utilizadas para la coordinación y cooperación de los hilos. Las variables locales de cada hilo en sus métodos son privadas del hilo, es decir, los hilos tienen pilas privadas.

Los segmentos de código dentro de un programa que accedan el mismo objeto desde hilos separados (concurrentes) se llaman regiones críticas. Java provee algunos métodos más para coordinar las actividades de los hilos, como notifyAll, wait, etc.

Suponga, por ejemplo, las colas compartidas descritas previamente en esta sección, las cuales tienen hilos de E/S e hilos de trabajo utilizados para transferir las solicitudes en arquitecturas de servidores basadas en hilos. Pueden aparecer condiciones de competencia (race conditions) cuando los hilos manipulan concurrentemente estructuras de datos del tipo de colas. Las solicitudes que residen en las colas pueden perderse o duplicarse. A no ser que los punteros de manipulación de los hilos hayan sido cuidadosamente coordinados.

Java proporciona a programadores la palabra clave synchronized para designar un monitor, que es un recurso de sincronización de hilos muy conocido. Los programadores designan métodos completos o bien bloques de código de tamaño arbitrario como pertenecientes a un monitor asociado a un objeto individual. La garantía de un monitor viene del hecho de que como máximo un hilo puede ejecutarse dentro de un monitor en cualquier instante. Podríamos seriar las acciones de los hilos de E/S y trabajadores en nuestro ejemplo designando los métodos añadirA() y eliminarDe() en la clase Cola como métodos synchronized. Todos los accesos a variables dentro de dichos métodos se realizan con exclusión mutua respecto a las invocaciones de estos métodos.

Java permite bloquear y despertar hilos a través de objetos arbitrarios que actúan como variables de condición. Un hilo que necesita bloquearse en espera de una cierta condición invoca un método wait(). Todos los objetos implementan este método, ya que pertenecen a la clase raíz de Java llamada Objet. Otro hilo invocara notify() para  desbloquear como máximo un hilo, o bien invocará a notifyAll() para desbloquear  todos los hilos en espera sobre el mismo objeto. Ambos métodos de notificación pertenecen también a la clase Objet.

Como ejemplo, cuando un hilo trabajador descubre que ya no hay mas solicitudes parar procesar, invoca wait() en la instancia Cola. Cuando posteriormente el hilo de E/S añada una solicitud a la cola, invocará el método notify() de gestión de colas, para despertar al trabajador.

Los métodos de sincronización de Java se muestran en la Figura 6.9. Además de las primitivas de sincronización mencionadas, el método join() bloquea al que invoca hasta la terminación del hilo destino. El método interrupt() es útil para despertar prematuramente un hilo en espera. Todas las primitivas estándar de sincronización, como tos semáforos, pueden implementarse en Java. Sin embargo es preciso hacerlo cuidadosamente ya que la garantía del monitor de Java se aplica única mente a código de objetos declarado como synchronized: una clase tendrá una mezcla de métodos synchronized y no-synchronized. Además el monitor implementado en un objeto Java tiene una única variable de condición implícita mientras que en general un monitor puede tener varias variables de condición.


thread.join(int milisegundos)

            Bloquea el hilo invocador durante el tiempo especificado hasta que el hilo        haya terminado.

 

thread.interrup()

            Interrumpe el hilo: le obliga a volver desde una llamada a método        bloqueante como sleep().

 

objet.wait(long milisegundos, int nanosegundos)

            Bloquea el hilo invocador hasta que una llamada realizada a notify() o notifyAll() en el objeto despierte el hilo, o bien el hilo sea interrumpido, o        bien el tiempo especificado sa haya cumplido.

 

objet.notify(), objet.notifyAll()

            Despierta, respectivamente, uno o todos los hilos que han invocado a wait()    en el objeto.

 

Llamadas de sincronización de hilos en Java.

Tiempos de vida de los hilos

Cada nuevo hilo se crea en la misma máquina virtual Java (JVM. Java Virtual Machine) que su creador y en estado SUSPENDIDO. Una vez que ha pasado a estado PREPARADO con el método start(). Ejecuta el método run() de un objeto designado en su constructor. JVM y los hilos que hay sobre él se ejecutan en un proceso sobre el sistema operativo subyacente. Los hilos pueden tener asignada una prioridad de forma que las implementaciones de Java que soportan prioridades ejecutarán cada hilo de forma preferente al resto de hilos con menor prioridad. Un hilo finaliza su vida cuando vuelve del método run(), o bien cuando se invoca el método destroy().

Los programas pueden gestionar los hilos en grupos. Cada hilo pertenece a un grupo, al que se le asigna en el momento de su creación. Los grupos de hilos son útiles cuando varias aplicaciones coexisten en la misma JVM. Un ejemplo de su uso es la seguridad: por defecto un hilo en un cierto grupo no puede gestionar operaciones sobre un hilo en otro grupo. De esta forma un hilo de una cierta aplicación no puede, de forma maliciosa, interrumpir un hilo del entorno de ventanas del sistema (AWT).

Los grupos de hilos también facilitan el control de las prioridades relativas de los hilos (en las implementaciones de Java que soporten prioridades). Esto es útil para visualizadores que ejecuten applets y para los servidores Web que ejecuten los programas llamados servlets, los cuales crean páginas Web de forma dinámica. Un hilo no privilegiado dentro de un applet o servlet únicamente puede crear un nuevo hilo que pertenezca a su propio grupo, o a un grupo de menor prioridad creado dentro del suyo: las restricciones exactas dependen del administrador de seguridad (Securitv Manager) que esté activo. Los visualizadores y los servidores pueden asignar hilos pertenecientes a diferentes applets o servlets a diferentes grupos y establecer la prioridad máxima de cada grupo en su conjunto (incluyendo los grupos descendientes). Para un hilo de applet o de servlet no existe forma de ignorar las prioridades de grupo impuestas por el gestor de hilos, ya que no pueden ser modificadas mediante llamadas a setPriority().

 

Planificación de hilos

 

Planificación apropiativa: un hilo puede suspenderse en cualquier punto para dejar paso a otro hilo, incluso aunque el hilo pueda seguir en ejecución.

Planificación no apropiativa: un hilo se ejecuta hasta él mismo realiza una invocación al sistema de gestión de hilos, siendo en ese momento cuando el sistema puede desalojarle para planificar otro hilo.

La ventaja de la planificación no apropiativa es que cualquier sección de código que no contenga una llamada al sistema de gestión de hilos es automáticamente una sección crítica. Así se pueden evitar cómodamente las condiciones de competencia. Por otro lado, los hilos planificados de forma no apropiativa no pueden aprovechar los sistemas multiprocesador, ya que se ejecutan de forma exclusiva. Es preciso tener cuidado con las secciones de código grandes que no contengan llamadas al sistema de gestión de hilos. El programador puede necesitar insertar invocaciones que permitan que otros hilos puedan planificarse y progresar en su trabajo. Los hilos planificados de forma no apropiativa no son aptos para su uso en aplicaciones en tiempo real, ya que en éstas los eventos llevan asociados tiempos absolutos en los que deben procesarse.

 

Implementación de hilos

 

En general cada dominio de tiempo real tiene sus propios requisitos de planificación de hilos. Es por lo tanto deseable que a veces las aplicaciones implementen sus propias políticas de planificación.

Muchos núcleos dan soporte para procesos multihilo de forma nativa. Estos núcleos proporcionan las llamadas al sistema de creación y gestión de hilos, y planifican de forma individual los hilos. Otros núcleos disponen únicamente de la abstracción de procesos monohilo. Los procesos multihilo deben entonces implementarse en una biblioteca de procedimientos enlazada a los programas de aplicación. En estos casos el núcleo no conoce estos hilos de nivel de usuario y por lo tanto no puede planificarlos independientemente. Una biblioteca en tiempo de ejecución de hilos organiza  su planificación. Un hilo podría bloquear al proceso si se realiza una llamada bloqueante al sistema, de forma que debe usarse la entrada - salida asíncrona del núcleo subyacente. Análogamente la implementación puede utilizar los temporizadores proporcionados por el núcleo y las posibilidades de interrupciones software para realizar el uso compartido de los tiempos entre hilos.

Cuando el núcleo no tiene soporte para procesos multihilo, las implementaciones al nivel de usuario de los hilos adolecen de estos problemas: Los hilos de un cierto proceso no pueden aprovecharse de la existencia de un multiprocesador. Un hilo que genera una falta de página bloquea el proceso completo y todos los hilos dentro de él. Los hilos de diferentes procesos no pueden planificarse de acuerdo a un único criterio de prioridad relativa.

Sin embargo las implementaciones de hilos del nivel de usuario tienen ventajas significativas sobre las implementaciones al nivel núcleo: Algunas operaciones sobre hilos son bastante más baratas. Por ejemplo la conmutación entre hilos pertenecientes al mismo proceso no supone necesariamente una llamada al sistema, es decir, una interrupción interna que es relativamente cara. Debido a que el módulo de planificación de hilos se implementa fuera del núcleo, puede personalizarse de forma que se adapte a los requisitos particulares de una cierta aplicación. Pueden soportarse muchos más hilos de nivel de usuario de los que el núcleo puede proporcionar por defecto.

Es posible combinar  las ventajas de las implementaciones de hilos de nivel usuario y de nivel de núcleo. Una posible aproximación es la de permitir al código de nivel de usuario proporcionar indicaciones de planificación al planificador de hilos del núcleo. Otra posibilidad es un tipo de planificación jerárquica. Cada proceso crea uno a más hilos de nivel de núcleo. También soporta hilos de nivel de usuario. Un planificado de nivel de usuario asigna cada hilo de nivel de usuario a un hilo de nivel de núcleo. Este esquema puede explotar los multiprocesadores y se beneficia del hecho de que algunas operaciones de creación y conmutación de hilos se realizan al nivel de usuario. La desventaja de éste esquema es su falta de flexibilidad: si un hilo se bloquea en el núcleo entonces a todos los hilos de nivel de usuario asignados a él se les impide la ejecución, independientemente de si tienen o no la posibilidad de ejecutarse.

Varios proyectos de investigación han desarrollado esquemas de planificación jerárquica más avanzados para obtener mayor eficiencia y flexibilidad. La idea conductora de estos diseños es que un planificador de nivel de usuario no sólo necesita del núcleo simplemente un conjunto de hilos soportados ya por el núcleo sobre los que se puedan vincular hilos de nivel de usuario. El planificado de nivel de usuario también necesita que el núcleo le notifique los eventos relevantes en sus decisiones de planificación.

Diseño de activaciones del planificador: Es una implementación de un sistema de planificación jerárquico basado en eventos. Considera que los principales componentes del sistema son un núcleo ejecutándose en un computador con uno o más procesadores y un conjunto de programas de aplicación ejecutándose sobre él. Cada proceso de aplicación contiene un planificador de nivel de usuario que se encarga de gestionar los hilos dentro del proceso. El núcleo es responsable de la asignación de procesadores virtuales de procesos. El número de procesadores virtuales asignados a un proceso depende de diferentes factores como los requisitos de la aplicación, sus prioridades relativas y la demanda total en los procesadores. Se llaman procesadores virtuales porque el núcleo puede asignar procesadores físicos diferentes a cada proceso a lo largo del tiempo, mientras se garantice el número de procesadores asignados.

El número de procesadores virtuales asignados a un proceso puede variar. Los procesos pueden devolver un procesador virtual que han dejado de necesitar; además pueden solicitar procesadores virtuales extra.

Una activación del planificador es una llamada desde el núcleo a un proceso que sirve para notificar al planificador del proceso la ocurrencia de un evento. El núcleo crea una activación del planificador cargando los registros físicos del procesador con un contexto que provoca la ejecución de código en el proceso, en una dirección de procedimiento designada por el planificador de nivel de usuario. Una activación del planificador puede de esta forma considerarse como una unidad de asignación de tiempo en un procesador virtual. El planificador de nivel de usuario tiene la tarea de asignar sus hilos preparados al conjunto de activaciones del planificador  que en ese momento se están ejecutando en él. El número de activaciones del planificador es como máximo el número de procesadores virtuales que el núcleo ha asignado al proceso.

Los cuatro tipos de eventos que el núcleo notifica al planificador de nivel de usuario (planificador) son los siguientes:

 

  • Procesador virtual asignado: el núcleo asigna un nuevo procesador virtual al proceso; el planificador puede cargar el SA (Activación del planificador) para recomenzar su ejecución.
  • SA bloqueado: un SA se ha bloqueado en el núcleo y éste está utilizando un nuevo SA para notificarlo el planificador.
  • SA desbloqueado: un SA que ha estado bloqueado en el núcleo se ha desbloqueado y esta preparado para ejecutarse de nuevo al nivel de usuario.
  • SA apropiado: el núcleo ha arrebatado el SA especificado al proceso.

 

En cada uno de estos eventos, el núcleo esta notificando de estos eventos al SA de notificación. Para crear un SA de notificación, el núcleo puede asignar a un procesador virtual nuevo al proceso o bien apropiarse de otro SA en mismo proceso, en el segundo caso la apropiación debe ser notificada para así volver a recalcular las asignaciones correspondientes de hilos a SA.

 

El esquema de planificación jerárquica es más flexible ya que el planificador de proceso de nivel de usuario puede asignar hilos a SA mediante cualquier política de conjunto de eventos de bajo nivel. En tanto el núcleo sigue con su comportamiento normal, ya que no influye en nada el comportamiento del planificador de nivel de usuario, pero ayuda al planificador mediante la notificación de eventos y proporcionando el estado de los registros de los hilos bloqueados y desalojados.

 

Comunicación e INVOCACIÓN:

 

En este punto nos concentraremos en la comunicación como parte de la implementación de lo que hemos llamado una invocación, es decir, construcción del tipo de las invocaciones remotas (llamadas a procedimientos remotos o notificación de eventos) cuyo propósito es el de efectuar una operación sobre un recurso en un espacio de direcciones diferentes.

Ahora trataremos cuestiones importantes de diseño y conceptuales de los sistemas operativos:

 

·  Primitivas de sincronización: Algunos núcleos diseñados para sistemas distribuidos han proporcionado primitivas de comunicación, similares a los diferentes tipos de invocación conocidos. La inserción de funcionalidad de comunicación relativamente de alto nivel en el núcleo tiene la ventaja de la eficiencia. Otro punto importante es el ahorro en la sobrecarga de las llamadas al sistema tiende a ser mayor con la comunicación en grupo.

En la práctica, es el middleware y no el núcleo el que proporciona la mayor parte de los recursos de comunicación de alto nivel que aparece en los sistemas actuales, incluyendo RPC/RMI, notificación de eventos y comunicación de grupos. El desarrollo de este software complejo es más sencillo a nivel de usuario que desarrollarlo para el núcleo. Los programadores normalmente implementan el middleware  sobre los sockets proporcionando acceso a los protocolos estándar de Internet, (TCP y UDP - protocolos de capa de transporte). Las principales razones de utilizar sockets son la portabilidad e interoperabilidad que posee. A pesar del amplio uso de sockets TCP y UDP proporcionado por los núcleos más comunes, aun se sigue investigando para conseguir primitivas de comunicación con menores costes sobre núcleos experimentales.

·  Protocolos y apertura: uno de los principales requisitos de los sistemas operativos es el de proporcionar protocolos estándar que permitan la intercomunicación entre implementaciones middleware sobre diferentes plataformas. Algunos núcleos de investigación en la década de los ochenta (80’) incorporaban sus propios protocolos de red ajustados para las interacciones con RPC, sin embargo estos protocolos no fueron ampliamente usados fuera de sus entornos de investigación nativos, y por ello los programadores decidieron dejar la elección de los protocolos de red como  una cuestión abierta. Estos núcleos proporcionan un sistema de paso de mensajes únicamente entre procesos locales y dejan el procesamiento del protocolo de red a un servidor que se ejecuta sobre el núcleo.

Dado los requisitos diarios de acceso a Internet, es necesario que los sistemas operativos sean compatibles al nivel TCP y UDP para todo, excepto para los dispositivos de red más pequeños. Además el sistema operativo debe  habilitar al middleware para que pueda sacar partido de los nuevos protocolos de bajo nivel.

Los protocolos se  organizan normalmente en una pila de niveles, donde muchos de los sistemas operativos permiten la integración estática de nuevos niveles, mediante la inclusión de un nivel como manejador (Driver) de protocolo instalado permanentemente, por lo contrario se lo realiza por la composición dinámica de protocolos, donde se ajusta de manera automática. El soporte para la composición de protocolos apareció en el diseño de los Streams de UNÍS (1984).

 

 

PRESTACIONES DE LA INVOCACION:

Las prestaciones de la invocación son un factor crítico en el diseño de sistemas distribuidos. Cuanto más separan los diseñadores de la funcionalidad entre espacios de direcciones, mas invocaciones remotas se necesitan. Los clientes y servidores pueden realizar muchos millones de operaciones asociadas a invocaciones  a lo largo de su vida, de forma que pequeñas fracciones de milisegundos son relevantes en los costes de invocación. Las tecnologías de red continúan mejorando pero los tiempos de invocación no han crecido en proporción al incremento del ancho de banda de las redes. Las sobrecargas de software predominan a menudo sobre las cargas de la red en los tiempos de invocación. Esto no ocurre en una invocación remota sobre Internet, por ejemplo para solicitar un recurso Web. El ancho de banda es a menudo bajo y la carga del servidor muchas veces predomina sobre los costes de procesamiento para cada solicitud. Las implementaciones de RPC y RMI han sido un tema de estudio debido a la amplia aceptación de estos mecanismos para el procesamiento cliente-servidor de propósito general.

 

COSTES DE INVOCACION:

 

La llamada y la invocación a un procedimiento convencional y a un método convencional, respectivamente. La realización de una llamada al sistema, el envió de un mensaje, la invocación a un procedimiento remoto y la invocación a un método remoto son ejemplos de mecanismos de invocación. Cada mecanismo provoca que se ejecute código fuera del ámbito del procedimiento u objeto que invoca. Cada invocación supone, en general, la comunicación de argumentos a este código y la devolución de datos al que invoca. Los mecanismos de invocación pueden ser síncronos, por ejemplo para el caso de llamadas a procedimientos convencionales o remotos, o asíncronos.

Los aspectos que afectan en mayor medida a las prestaciones de los mecanismos de invocación, a parte de si son o no síncronos, son si estos suponen una transición de dominio(es decir, si se cambia de espacio de direcciones), implican comunicaciones a través de la red y si suponen planificación y comunicación de hilos.

 


Invocacion Utilizando La Red:

 

Un RPC nulo(al igual que un RMI nulo) se define como un RPC sin parámetros que ejecuta un procedimiento nulo y no devuelve valores. Su ejecución supone un intercambio de mensajes que lleva muy pocos datos al sistema y ningún dato al usuario. Los costes de las invocaciones nulas(RPC, RMI)tienen mucha importancia ya que miden una sobrecarga fija, la latencia. Los costes de invocación se incrementan con los tamaños de los argumentos y resultados, pero en muchos casos la latencia es significativa en comparación con el resto del retardo.

El retardo es aproximadamente, proporcional al tamaño, hasta que este tamaño alcanza un umbral del tamaño del paquete de red. Por encima de este umbral debe enviarse al menos un paquete adicional para llevar los datos extras. En función del protocolo, puede usarse otro paquete más para reconocer la llegada de este paquete extra. El retardo o es el único valor de interés en una implementación de RPC; también esta implicado el ancho de banda de RPC(o productividad) cuando hay que transferir datos en masa. Se trata de la tasa de transferencia de datos entre computadores en un único RPC. Según se incrementa la cantidad de datos, el ancho de banda también se incrementa ya que las sobrecargas pasan a ser menos significativas.

 

 

Los pasos en un RPC son los siguientes (RMI realiza pasos similares):

 

·        El resguardo del procedimiento del cliente empaqueta los argumentos de llamada dentro de un mensaje, envía el mensaje de solicitud y recibe y desempaqueta la respuesta.

·        El servidor, un hilo de trabajo recibe la solicitud entrante, o bien un hilo de E/S recibe la solicitud y se la envía a un hilo; en cualquier caso el trabajador invoca al resguardo apropiado del procedimiento del servidor.

·        El resguardo del servidor desempaqueta el mensaje de solicitud, invoca el procedimiento designado y empaqueta y envía la respuesta.

 

Principales componentes significativos en el retardo de invocación remota:

Empaquetamiento: al incrementarse la cantidad de datos suponen una sobrecarga significativa.

Copia De Datos: potencialmente, incluso después del empaquetamiento, los datos del mensaje son copiados varias veces durante un RPC.

 

1) Entre el espacio de direcciones del cliente o del servidor y los buffers del núcleo.

2) Sobre cada nivel de protocolo (por ejemplo RPC/UDP/IP/ethernet).

3) Entre el interfaz de red y los buffers del núcleo.

 

Las transferencias entre la interfaz de red y la memoria principal son gestionadas normalmente por el acceso directo a memoria (DMA).El procesador gestiona el resto de copias.

Inicialización de paquetes: supone la inicialización de las cabeceras y terminaciones del protocolo, incluyendo los checksum. El coste es por lo tanto proporcional, en parte a la cantidad de datos enviados.

 

Planificación de hilos y conmutación de contexto: puede ocurrir de la siguiente forma:

 

1) En un RPC se realizan varias llamadas el sistema(es decir, cambios de contexto) al invocar        los resguardos las operaciones de comunicación del núcleo.

2) Se planifican uno o más hilos en el servidor.

3) Si el sistema operativo utiliza un proceso independiente de gestión de red, entonces cada

 

Envía supone un cambio de contexto a uno de sus hilos.

Espera por reconocimiento: la elección del protocolo RPC puede influir en los retardos y en particular cuando se envían grandes cantidades de datos.

 


COMPARTICION DE MEMORIA:

 

Las regiones compartidas pueden utilizarse para una comunicación  rápida entre un proceso de usuario y el núcleo, o bien entre procesos de usuarios. Los datos se comunican mediante la escritura y la lectura en la región compartida. De esta forma los datos son enviados eficientemente, sin necesidad de copiarlos hacia o desde el espacio de direcciones del núcleo. Sin embargo, se pueden necesitar llamadas al sistema e interrupciones software para la sincronización, por ejemplo cuando el proceso de usuario ha escrito datos que deben ser transmitidas o cuando el núcleo ha escrito datos que deben ser consumidos por el proceso de usuario. Por supuesto una región compartida solo se justifica cuando se utiliza suficientemente, de forma que se amortiza el coste de inicialización.

Incluso si se utilizan regiones compartidas, el núcleo debe copiar los datos desde cada buffer a las interfaces de red. La arquitectura U-Net(von Eicken y otros 1995) permite el código de nivel de usuario acceder directamente a la interfaz de red propia de forma que el código de nivel de usuario puede transferir datos a la red sin necesidad de copiarlos.

 

Elección del protocolo.

 

El retardo que sufre un cliente durante las interacciones solicitud-respuesta sobre TCP no es peor que sobre UDP en ocasiones es menor. El comportamiento del almacenamiento en TCP puede impedir la obtención de buenas prestaciones, y sus sobrecargas de conexión son una desventaja en comparación con UDP. Las sobrecargas de conexión de TCP son particularmente evidentes en las invocaciones Web, debido a que HTTP 1.0 realiza una conexión TCP diferente en cada invocación. Además que en muchos casos el algoritmo de arranque lento de TCP afecta retrasando la transferencia de datos HTTP de forma innecesaria. Nielson encontró que la desactivación del almacenamiento por defecto proporcionado por el sistema operativo podría tener un impacto significativo en el retardo de invocación. Por esta razón el sistema operativo no envía los datos sobre la red inmediatamente después de la llamada de sockets write(). Nielson llego a la conclusión de que para el caso de HTTP 1.1 el comportamiento del almacenamiento por defecto del sistema operativo podría causar significativos retardos innecesarios debidos a los tiempos límites. Pare eliminar estos retardos la configuración del TCP en el núcleo para forzar el envió a la red de cada solicitud HTTP de forma individual.

 

Invocación dentro de un computador.

 

Bershad realizo un estudio de una instalación examinada donde, la mayor parte de las invocaciones entre espacios de direcciones se realizaban dentro de un computador y no, como en una instalación cliente-servidor, entre diferentes computadores. En figura sugiere que una invocación a un espacio de direcciones diferente se implementa dentro de un mismo computador de la misma forma que entre computadores diferentes, excepto en que el sistema de paso de mensajes subyacente actúa de forma local, este ha sido a menudo el modelo implementado. Bershad desarrollo un mecanismo de invocación más diferente, llamado RPC de peso ligero (LRPC, light weight RPC), para el caso de dos procesos en la misma maquina. Se dieron cuenta que debería ser más eficiente la utilización de regiones de memoria compartida para la comunicación cliente-servidor, con una región diferente entre el servidor y

cada uno de sus clientes, esta región contiene una o más pila A (de Argumento: vease la Figura). En LRPC, los argumentos se copian una sola vez: cuando son empaquetados en la pila A. En un RPC equivalente, son copiados cuatro veces: desde la pila del resguardo del cliente hacia un mensaje; desde el mensaje al búfer del núcleo; desde el núcleo al mensaje del servidor; desde el mensaje del servidor a la pila del resguardo del cliente. Puede haber varias pilas A en una región compartida, debido a que varios hilos en el mismo cliente pueden invocar al servidor al mismo tiempo. En la figura se muestra una invocación, un hilo cliente entra en el entorno de ejecución del servidor realizando una interrupción software  hacia el núcleo y presentando al núcleo una capacidad. El núcleo lo comprueba y permite un  ámbito de contexto hacia un procedimiento valido del servidor: si es valido, el núcleo cambia el contexto del hilo para llamar al procedimiento en el entorno de ejecución del servidor. Cuando el procedimiento en el servidor termina, el hilo vuelve al núcleo, el cual cambia el hilo hacia atrás, hacia el entorno de ejecución del cliente. Hay que resaltar que tanto los clientes como el servidor emplean procedimientos resguardo pare ocultar a los programadores de aplicaciones los detalles descritos.

 

 

Discusión de LRPC.

 

Hay pocas dudas acerca de que LRPC es más eficiente que RPC en el caso local, mientras se realicen suficientes invocaciones. Bershad obtuvo valores de retardo pare LRPC menores en un factor de tres que los valores de los RPC ejecutados de forma local. La transparencia de ubicación no se sacrifica en la implementación de Bershad. Un resguardo del cliente examina un bit actualizado durante el enlace que indica si el servidor es local o remoto, y utiliza LRPC  RPC respectivamente. Las mejoras se refieren en su mayor parte a la eliminación de interrupciones software hacia el núcleo y a la planificación de procesadores de forma que se eliminen transiciones de dominio innecesarias. Por ejemplo si un procesador esta ocioso en el contexto de gestión de memoria del servidor, entonces el hilo debe transferirse a ese procesador, al mismo tiempo el procesador del cliente puede ser usado por otro hilo en el cliente.

 

OPERACION ASINCRONICA

 

Hemos discutido como el sistema operativo puede ayudar al nivel de middleware a proporcionar mecanismos de invocación remota eficientes. Sin embargo, hemos observado que en el entorno de Internet los efectos de las elevadas latencias, bajos anchos de banda y elevadas cargas del servidor pueden superar cualquier beneficio que el sistema operativo pueda proporcionar. A esto se le puede añadir el fenómeno de de desconexión y reconexión de la red, que puede considerarse como el causante de latencias de comunicación extremadamente elevadas. Los usuarios de computación móvil no están conectados a la red todo el tiempo. Incluso si tienen acceso a una red de área global sin hilos estarán obligatoriamente desconectados cuando, por ejemplo, su tren entre en un túnel.

 

Una técnica muy utilizada para vencer las latencias muy elevadas es la operación asíncrona, la cual aparece en dos modelos de programación: invocaciones concurrentes e invocaciones asíncronas.

 

REALIZANDO OPERACIONES CONCURRENTEMENTE

 

Un buen ejemplo de este tipo de aplicaciones son los navegadores Web. Una página Web normalmente contiene varias imágenes. El navegador debe pedir cada una de estas imágenes en solicitudes individuales de tipo HTTP GET (ya que los servidores Web HTTO 1.0 estándar únicamente soportan solicitudes para recursos individuales). El navegador no necesita obtener las imágenes en una secuencia en particular, de forma que realiza solicitudes concurrentes, normalmente hasta 4 a la vez. De esta forma el tiempo empleado para completar todas las solicitudes de imágenes es normalmente menor que el retardo en hacer las mismas solicitudes en serie. Pero no solo se reduce el retardo de comunicación total ya que, en general, el navegador puede solapar las actividades de computación de tipo de representación de imágenes con la comunicación.

 

INVOCACIONES ASINCRONAS

 

Una invocación asíncrona es aquella que se realiza de forma asíncrona respecto al invocador. Es decir, se realiza con una llamada no bloqueante, la cual retorna tan pronto como el mensaje de solicitud de invocación ha sido creado y esta preparado para ser enviado.

 

Algunas veces el cliente no necesita respuesta (excepto posiblemente una indicación de fallo si el nodo destino no puede ser alcanzado). Por ejemplo, las invocaciones de una dirección de CORBA tienen semántica pudiera. En caso contrario el cliente utiliza una llamada separada para obtener los resultados de la invocación. Por ejemplo, el sistema de comunicación Mercurio soporta invocaciones asíncronas. Una operación asíncrona devuelve un objeto llamado promesa. Finalmente, cuando la invocación tiene éxito o bien se considera que ha fallado, el sistema Mercury pone el estado y cualquier valor de retorno en la promesa. El que invoca utiliza la operación reclamación para obtener los resultados desde la promesa. La operación reclamación se bloquea hasta que la promesa esta preparada, con lo que devuelve los resultados o las excepciones desde la llamada. La operación preparado esta disponible para comprobar una promesa sin necesidad de bloquearse: devuelve cierto o falso de si la promesa esta preparada o bloqueada.

 

INVOCACIONES ASINCRONAS PERSISTENTES.

 

Los mecanismos de invocación asíncrona tradicionales como las invocaciones Mercury y las invocaciones de una dirección de CORBA son implementadas mediante streams TCP y fallan sin un streams, es decir, si el enlace de red esta fuera de servicio o el noto destino deja de funcionar.

 

Sin embargo, un modelo de invocación asíncrona mas desarrollado, al que llamaremos invocación asíncrona persistente, esta resultando cada vez más relevante debido a la operación desconectada. Este modelo es similar a Mercury respecto a las operaciones de programación que proporciona, pero la diferencia estriba en la semántica de fallos. Un mecanismo de invocación convencional (síncrono o asíncrono) esta diseñado para fallar después de que han ocurrido un cierto numero de timeouts. Sin embargo, a menudo estos timeouts a corto plazo no son apropiados cuando se generan desconexiones o latencias muy elevadas.

 

Un sistema de invocación asíncrona persistente intenta realizar la invocación indefinidamente, hasta que puede determinar que ha tenido éxito o ha fracasado, o hasta que la aplicación cancela la invocación. Un ejemplo es QRPC (RPC en colas) en el conjunto de herramientas Rover para acceso a información móvil.

 

Tal y como el nombre sugiere, QRPC inserta en colas, realizando un registro estable, las solicitudes de invocaciones salientes mientras no exista conexión de red y planifica las operaciones que son enviadas a los servidores a través de la red cuando existe conexión. De forma similar en colas en el servidor los resultados de las invocaciones en lo que se puede considerar como el buzón de invocaciones del cliente, hasta que el cliente vuelva a conectarse y los obtenga. Las solicitudes y los resultados pueden comprimirse al insertarse en las colas, antes de ser transmitidos sobre una red de pequeños anchos de banda.

 

Arquitectura del sistema operativo:

 

Sistema distribuidos

 

Un sistema distribuido abierto debería posibilitar lo siguiente:

 

  • Ejecutar en cada computador únicamente el software de sistema que sea necesario para jugar su papel particular en la arquitectura del sistema: los requisitos de sistemas pueden variar entre, por ejemplo, asistentes digitales personales y servidores de cálculo dedicados. La carga de módulos redundantes desperdicia los recursos de memoria.
  • Permitir al software (y al computador) implementar la posibilidad de que cualquier servicio particular sea cambiado independientemente de otros recursos.
  • Permitir que se puedan proporcionar diferentes alternativas para el mismo servicio, cuando ello sea requerido por los diferentes usuarios o aplicaciones.
  • Introducir nuevos servicios sin dañar la integridad de los ya existentes.

 

La separación  entre los mecanismos de  gestión de  recursos fijos y la política de gestión de recursos, las cuales varían entre diferente aplicaciones y entre diferente servicios, ha sido durante mucho tiempo un principio guía en el diseño de los sistemas operativos.

 

Núcleo monolítico y micro núcleo

 

En el diseño de los núcleos existen: la aproximación monolítica y el micro núcleo. Estos diseños difieren básicamente en la decisión sobre que funcionalidad pertenece al núcleo y que se deja al proceso servidor que puede ser cargado dinámicamente para ejecutarse sobre él. A pesar de que el micro núcleos no está extendidos. Es instructivo entender sus ventajase inconvenientes comparándolos con los núcleos típicos existentes actualmente.

 

Un núcleo monolítico puede contener algunos procesos servidores que se ejecutan dentro de su espacio de direcciones, incluyendo servidores de archivos y de red. El código que ejecutan estos procesos es parte de la configuración estándar del núcleo.

 

Monolítico: (Chambers), pilar  o una columna o una simple piedra: Cualquier cosa que recuerde la uniformidad de  monolito, carácter masivo e inflexibilidad

Para el diseño del micro núcleo, el núcleo proporciona únicamente las abstracciones más básicas, principalmente espacio de direcciones, hilos y comunicación local  entre procesos: el resto de servicio del sistema vienen dado por servidores que se cargan dinámicamente, precisamente en aquellos computadores del sistema distribuido que lo requieran.  Los clientes acceden a esos servicios del sistema utilizando los mecanismos de innovación basados en mensajes proporcionados por el núcleo.

Además la extensibilidad, los diseñadores de micro núcleos tienen otros objetivos: La emulación binaria de sistemas operativos estándar como el Unix.

El micronúcleo aparece como un nivel entre el hardware  el que forman los  principales componentes del sistema, llamados subsistemas. Si las prestaciones son el principal objetivo, en lugar de la portabilidad, entonces el middleware puede utilizar directamente los servicios del micronúcleo. En otro caso, utiliza un lenguaje con un subsistema de soporte en tiempo de ejecución, o bien una interfaz de sistema operativo  de alto nivel proporcionado por un subsistema de emulación de sistema operativo. Cada uno de ello se implementa mediante una combinación de procedimiento de biblioteca enlazada dentro de las aplicaciones y un conjunto de servidores ejecutándose sobre el micro núcleo.

Puede existir más de  una interfaz de llamadas a los sistemas (más de unos sistemas operativos) a disposición del programador en la misma plataforma. Esta situación es una reminiscencia de la arquitectura de la IBM 370, cuyo sistema VM puede presentar varias maquinas virtuales completas  a diferentes programas que se ejecutan el mismo computador (monoprocesador).

 

Comparación

 

Las principales ventajas de un sistema operativo basado en micronúcleo son su extensibilidad y su capacidad para hacer cumplir la modularidad por encima de los límites de protección de memoria. La ventaja de un diseño monolítico es la eficiencia relativa con que se invocan las operaciones. Las llamadas al sistema pueden ser más caras que los procedimientos convencionales, e incluso utilizando algunas técnicas, una invocación a un espacio de direcciones de nivel de usuario separado en el mismo nodo es todavía más costosa.

 

La falta de estructura en los diseños monolíticos puede evitarse utilizando ingeniería de Software como ser el diseño por niveles o el diseño orientado a objetos. Windows NT utiliza una combinación de ambos y sin embargo, sigue siendo masivo y la mayor parte de su funcionalidad no está diseñada para ser reemplazada en forma rutinaria. Incluso, un núcleo grande modularizado puede ser difícil de mantener y proporciona un soporte muy limitado para un sistema distribuido abierto. Mientras los módulos se ejecuten dentro de un espacio de direcciones utilizando un lenguaje del tipo C o C++, que genera código con el objetivo de la eficiencia pero permite acceso a datos de forma arbitraria, es posible un abandono de la modularidad por parte de programadores que busquen  implementaciones eficientes, y que un error corrompa los datos de otro.

ALGUNAS APROXIMACIONES HÍBRIDAS

 

Dos de los micronúcleos originales, Mach y Chorus, comenzaron su evolución ejecutando los servidores únicamente como procesos de usuario, lo que aseguraba modularidad por el hardware mediante los espacios de direcciones. Cuando los servidores necesiten acceso directo al hardware se proporcionan llamadas especiales al sistema para esos procesos privilegiados, las cuales vincularán registros de dispositivos y bufferes sobre sus espacios de direcciones. El núcleo convierte las interrupciones en mensajes que permiten el manejo de interrupciones a los servidores de nivel usuario. Debido a problemas en las prestaciones, Mach y Chorus cambiaron permitiendo a los servidores cargarse dinámicamente sobre el espacio de direcciones del núcleo o sobre el espacio de direcciones de nivel usuario. Los clientes interactúan con los servidores utilizando las mismas llamadas de comunicación entre procesos. Un problema es que la depuración por parte de un programador de un servidor a nivel de usuario, permitiéndole ejecutarse dentro del espacio de direcciones del núcleo, amenaza la integridad del sistema por cualquier error de programación.

El diseño del sistema operativo SPIN, en cambio, afronta el problema de ceder eficiencia por protección, mediante el empleo de servicios de protección en el lenguaje. El núcleo y todos los módulos cargados dinámicamente al núcleo se ejecutan en un único espacio de direcciones. Para estar mutuamente protegidos, todos ellos se escriben en un lenguaje de tipos seguro como Modula-3 . Ningún módulo insertado al núcleo puede acceder a un recurso amenos que fuera gestionada una referencia a él y, Modula-3 fuerza el hecho de que una referencia sólo se puede utilizar para operaciones permitidas por el programador. Para minimizar las dependencias entre módulos, los diseñadores de SPIN eligen un modelo basado en eventos como interacción entre módulos insertados en el espacio de direcciones del núcleo, definiendo eventos centrales como ser llegada de un paquete a la red, interrupciones del temporizador, faltas de página y cambio de estado en los hilos. Los componentes se registran a sí mismos como manejadores  de los eventos que los afectan. Por ejemplo, un planificador se registrará como gestor de eventos del sistema de activaciones del planificador.

Los sistemas operativos del tipo Némesis explotan el hecho de que incluso a nivel de hardware, un espacio de direcciones no es necesariamente un único dominio de protección. Gracias a la llegada de procesadores de 64 bits que soportan espacios de direcciones muy grandes, se emplea un único gran espacio de direcciones donde coexisten módulos de sistema y aplicaciones cargados en tiempo de ejecución,  configurando regiones individuales protegidas, con acceso completo a sus propias regiones y compartido en forma selectiva a las demás.

 

Algunos diseños más recientes como L4 y ExoKernel basados en micronúcleos contienen excesiva política en relación con mecanismos. L4 obliga a los módulos a ejecutarse en espacios de direcciones de nivel usuario pero optimiza la comunicación entre procesos. ExoKernel, en cambio, se basa en el empleo de bibliotecas de nivel usuario para generar las extensiones funcionales. Proporciona asignación protegida de recursos esperando que las demás gestiones se realice mediante el enlace de bibliotecas en las aplicaciones.

 

La cuestión todavía pendiente estriba en cómo generar una arquitectura de sistema operativo lo suficientemente extensible con buenas prestaciones en comparación con los diseños monolíticos.

 

Anterior            Índice           Siguiente

   Anterior          Índice          Siguiente

Para mayor información, seleccione una opción:

Número de visitas efectuadas desde el 17/12/2001: 
 
Estadísticas diarias desde el 10/07/2002:    

Número de visitantes actuales disponible desde el 14/07/2002:

 

AddFreeStats.com Free Web Stats in real-time !  

 

 

 

Autor: lrmdavid@exa.unne.edu.ar

Ó FACENA - http://exa.unne.edu.ar

Servicios WEB: webmaster@exa.unne.edu.ar