3.1
Concepto de hilo
Un hilo es un flujo de control dentro de un proceso, una unidad básica de utilización de la CPU; comprende un contador de programa, un conjunto de registros y una pila. Comparte con otros hilos que pertenecen al mismo proceso la sección de código, la sección de datos y otros recursos del sistema operativo como los archivos abiertos y las señales. Los hilo son subprocesos generados por un proceso padre o por el kernel para facilitar y optimizar el uso del CPU, se encargan de almacenar, copiar cargar datos (etc) utilizando los recursos que fueron asignados al proceso que se ejecute 3.1.1 Multihilo Múltihilo se refiere a la capacidad de un sistema operativo se dar soporte a múltiples hilos de ejecución en un solo proceso, en el que no se identifica con el concepto de hilo, se conoce como estrategia monohilo. Las dos configuraciones que se muestran en la parte izquierda de la figura son estrategia monohilo. Un ejemplo de sistema operativo que soporta un único proceso de usuario y un único hilo es el MS-DOS. Otros sistemas operativos soportan múltiples procesos de usuario, pero solo un hilo por proceso. La parte derecha de la Figura representa las estrategias múltihilo. El entorno de ejecución Java es un ejemplo de sistema con un único proceso y múltiples hilos. Lo interesante en esta sección es el uso de múltiples procesos, cada uno de los cuales soporta múltiples hilos. En un entorno múltihilo, un proceso se define como la unidad de asignación de recursos y una unidad de protección. Se asocian con procesos los siguientes: -
Un espacio de direcciones virtuales que soporta la imagen del proceso.
-
Acceso protegido a procesadores, otros procesos (para comunicación entre procesos), archivos y recursos de E/S (dispositivos y canales). Dentro de un proceso puede haber uno o más hilos, cada uno con:
-
Un estado de ejecución por hilo (Ejecutando, Listo, etc.).
-
Un contexto de hilo que se almacena cuando no está en ejecución; una forma de ver a un hilo es como un contador de programa independiente dentro de un proceso.
-
Una pila de ejecución
-
Por cada hilo, espacio de almacenamiento para variables locales.
-
Acceso a la memoria y recursos de su proceso, compartido con todos los hilos de un mismo proceso
La próxima figura muestra la diferencia entre los hilos y procesos desde el punto de vista de gestión de proceso. En un modelo de proceso incluye su bloque de control de proceso y el espacio.
3.1.2 Funcionabilidad de los hilos
La principal razón de tener hilos es que en muchas aplicaciones se desarrollan varias
actividades a la vez. Algunas de ésas se pueden bloquear de vez en cuando. Al descomponer una aplicación en varios hilos secuenciales que se ejecutan en cuasi-paralelo, el modelo de programación se simplifica.
Un segundo argumento para tener hilos es que, como son mas ligeros que los
procesos, son más fáciles de crear(es decir, rápidos) y destruir. En muchos sistemas, la creación de un hilo es de 10 a 100 veces más rápida que la de un proceso. Cuando el número de hilos necesarios cambia de manera dinámica y rápida, es útil tener esta propiedad.
Una tercera razón de tener hilos es un argumento relacionado con el rendimiento.
Los hilos no producen un aumento en el rendimiento cuando todos ellos están ligados en la CPU, pero cuando hay cantidad considerable de cálculos y operaciones de E/S, al tener hilos estas actividades se pueden traslapar, con lo cual se agiliza la velocidad de la aplicación.
Los hilos son útiles en los sistemas con varias CPUs, en donde es posible el
verdadero paralelismo.
Lleva mucho menos tiempo crear un nuevo hilo en un proceso existente que crear
un proceso totalmente nuevo.
Lleva menos tiempo finalizar un hilo que un proceso
Leva menos tiempo cambiar entre dos hilos dentro del mismo proceso.
Los hilos mejoran la eficiencia de la comunicación entre diferentes programas que
están ejecutando. 3.1.3 Estado de hilos Ejecutando, Listo y Bloqueado. El estado delos hilos está asociado al estado del proceso, sabiendo esto se definen las operaciones:
Creación: Cuando se crea un nuevo proceso, también se crea un hilo de dicho
proceso. Posteriormente, un hilo del proceso puede crear otro hilo dentro del mismo proceso, proporcionando un puntero a las instrucciones y los argumentos para el nuevo hilo. Al nuevo hilo se le proporciona su propio registro de contexto y espacio de pila y se coloca en la cola de Listos.
Bloqueo: Cuando un hilo necesita esperar por un
evento se bloquea, almacenan los registros de usuario, contador de programa y punteros de pila. El procesador puede pasar a ejecutar otro hilo en estado listo, dentro del mismo proceso o en otro diferente.
Desbloqueo: Cuando sucede el evento por el que
el hilo está bloqueado, el hilo se pasa a la cola de listos.
Finalización: Cuando se completa un hilo, se liberan su registro de contexto y pila.
3.1.4 Paralelismo Configuración del sistema, donde la generación de hilos se da en espacio de usuario y el espacio de kernel, la relación entre los hilos generados por ambos espacios va a depender del sistema o del proceso en ejecución. •
Los hilos pueden utilizarse para expresar algoritmos inherentemente paralelos. Se obtiene mayor rendimiento debido al hecho de que los hilos funcionan muy bien en sistemas multiprocesadores. Los hilos permiten expresar el paralelismo de alto nivel a través de un lenguaje de programación.
•
La utilización de múltiples hilos, puede conseguir un grado de paralelismo que incremente el rendimiento de un programa, e incluso hacer más fácil la escritura de su código.
En el multiprocesamiento la ejecución es paralela de distintos fragmentos de un mismo programa en distintos procesadores.
Paralelismo de grano fino en el cual el uso del paralelismo es mucho más complejo que el que se consigue con el uso de hilos. Si bien gran parte del trabajo se realiza en aplicaciones muy paralelas, este es un campo, hasta el momento, muy especializado y fragmentado, con varias soluciones diferentes.
3.1.5 Hilos a nivel de usuario y de núcleo
Hilos de nivel de usuario. En un entorno ULT (User-level threads) puro, la
aplicación gestiona todo el trabajo de los hilos y el núcleo no es consciente de la existencia de los mismos. El soporte para los hilos de usuario se proporciona por encima del kernel y las hebras se gestionan sin soporte del mismo. Ventajas y desventajas: a.
El cambio de hilo no requiere de privilegios de modo núcleo porque todas las
estructuras de datos de gestión de hilos están en el espacio de direcciones de usuario de un solo proceso. Por consiguiente, el proceso no cambia a modo núcleo para realizar la gestión de hilos. b.
La planificación puede especificarse por parte de la aplicación. Una aplicación se
puede beneficiar de un simple algoritmo de planificación cíclico, mientras que otra se podría beneficiar de un algoritmo de planificación basado en prioridades. c.
Los ULT pueden ejecutar en cualquier sistema operativo. No se necesita ningún
cambio en el nuevo núcleo para dar soporte a los ULT. La biblioteca de los hilos es un conjunto de utilidades a nivel de aplicación que comparten todas las aplicaciones. Desventajas: a.
En un sistema operativo típico muchas llamadas al sistema son bloqueantes. Como
resultado, cuando un ULT realiza una llamada al sistema, no sólo se bloquea ese hilo, sino que se bloquean todos los hilos del proceso. b.
En una estrategia pura ULT, una aplicación multihilo no puede sacar ventaja del
multiproceso. El núcleo asigna el proceso a un solo procesador al mismo tiempo. Por consiguiente, en un determinado momento sólo puede ejecutar un hilo del proceso.
Hilos a nivel de núcleo: En un entorno KLT(Kernel-level thread) puro, el nucleo
gestiona todo el trabajo de gestión de hilos. No hay código de gestión de hilos en la aplicación, solamente una interfaz de programación de aplicación (API) para acceder a las utilidades de hilos del núcleo.
Ventajas: a.
El núcleo puede planificar simultáneamente múltiples hilos de un solo proceso en
múltiples procesadores. b.
Si se bloquea un hilo de un proceso, el núcleo puede planificar otro hilo del mismo
proceso. c.
Las rutinas del núcleo pueden ser en sí mismas multihilo.
Desventajas: La transferencia de control de un hilo a otro del mismo proceso requiere un cambio de modo al núcleo. 3.1.6 Otras estructuras:
Relación muchos-a-muchos: El modelo
muchos-a-muchos multiplexa muchos hilos de usuario sobre un número menor o igual de hilos del kernel. El número de hilos del kernel puede ser específico de una determinada aplicación o de una determinada máquina.
Relación uno-a-muchos: Un hilo puede migrar de un entorno de proceso a otro.
Esto permite a los hilos moverse fácilmente entre distintos sistemas. Los hilos se pueden mover de un espacio de direcciones a otro, incluso fuera de los límites de la máquina (moverse de una computadora a otra). Según se mueve el hilo, debe llevarse determinada información con él, tal como el controlador de terminal, los parámetros globales y las guías de planificación. 3.2 MULTIPROCESO SIMÉTRICO. Tradicionalmente, el computador ha sido visto como una máquina secuencial. La mayor parte de los lenguajes de programación requieren que el programador especifique algoritmos como una secuencia de instrucciones. Un procesador ejecuta programas a través de la ejecución de instrucciones máquina en secuencia y de una en una. Cada instrucción se ejecuta como una secuencia de operaciones (ir a buscar la instrucción, ir a buscar los operando, realizar la operación, almacenar resultados).
Esta visión del computador nunca ha sido totalmente cierta. A nivel de micro-operación, se generan múltiples señales de control al mismo tiempo. El pipeline de instrucciones, al menos en lo relativo a la búsqueda y ejecución de operaciones, ha estado presente durante mucho tiempo. A medida que ha evolucionado la tecnología de los computadores y el coste del hardware ha descendido, los diseñadores han visto cada vez más oportunidades para el paralelismo, normalmente para mejorar el rendimiento y, en algunos casos, para mejorar la fiabilidad. 3.2.1 ARQUITECTURA SMP. Es útil ver donde encaja la arquitectura SMP dentro de las categorías de procesamiento paralelo. La forma más común de categorizar estos sistemas es la taxonomía de sistemas de procesamiento paralelo introducida por Flynn [FLYN72]. Flynn propone las siguientes categorías de sistemas de computadores: • Única instrucción, único flujo de datos – Single instruction single data (SISD) stream. Un solo procesador ejecuta una única instrucción que opera sobre datos almacenados en una sola memoria. • Única instrucción, múltiples flujos de datos – Single instruction multiple data (SIMD) stream. Una única instrucción de máquina controla la ejecución simultánea de un número de elementos de proceso. Cada elemento de proceso tiene una memoria de datos asociada, de forma que cada instrucción se ejecuta en un conjunto de datos diferente a través de los diferentes procesadores. Los procesadores vectoriales y matriciales entran dentro de esta categoría. • Múltiples instrucciones, único flujo de datos – Multiple instruction single data (MISD) stream. Se transmite una secuencia de datos a un conjunto de procesadores, cada uno de los cuales ejecuta una secuencia de instrucciones diferente. Esta estructura nunca se ha implementado. • Múltiples instrucciones, múltiples flujos de datos – Multiple instruction multiple data (MIMD) stream. Un conjunto de procesadores ejecuta simultáneamente diferentes secuencias de instrucciones en diferentes conjuntos de datos. Con la organización MIMD, los procesadores son de propósito general, porque deben ser capaces de procesar todas las instrucciones necesarias para realizar las transformaciones de datos apropiadas.
MIMD se puede subdividir por la forma en que se comunican los procesadores (Figura 1.1). Si cada procesador tiene una memoria dedicada, cada elemento de proceso es en sí un computador. La comunicación entre los computadores se puede realizar a través de rutas prefijadas o bien a través de redes. Este sistema es conocido como un cluster, o multicomputador. Si los procesadores comparten una memoria común, entonces cada procesador accede a los programas y datos almacenados en la memoria compartida, y los procesadores se comunican entre sí a través de dicha memoria; este sistema se conoce como multiprocesador de memoria compartida. Una clasificación general de los multiprocesadores de memoria compartida se basa en la forma de asignar procesos a los procesadores. Los dos enfoques fundamentales son maestro/esclavo y simétrico. Con la arquitectura maestro/esclavo, el núcleo del sistema operativo siempre ejecuta en un determinado procesador. El resto de los procesadores sólo podrán ejecutar programas de usuario y, a lo mejor, utilidades del sistema operativo. El maestro es responsable de la planificación de procesos e hilos. Una vez que un proceso/hilo está activado, si el esclavo necesita servicios (por ejemplo, una llamada de E/S), debe enviar una petición al maestro y esperar a que se realice el servicio. Este enfoque es bastante sencillo y requiere pocas mejoras respecto a un sistema operativo multiprogramado uniprocesador. La resolución de conflictos se simplifica porque un procesador tiene el control de toda la memoria y recursos de E/S. Las desventajas de este enfoque son las siguientes: • Un fallo en el maestro echa abajo todo el sistema. • El maestro puede convertirse en un cuello de botella desde el punto de vista del rendimiento, ya que es el único responsable de hacer toda la planificación y gestión de procesos. En un multiprocesador simétrico (Symmetric Multiprocessor, SMP), el núcleo puede ejecutar en cualquier procesador, y normalmente cada procesador realiza su propia planificación del conjunto disponible de procesos e hilos. El núcleo puede construirse como múltiples procesos o múltiples hilos, permitiéndose la ejecución de partes del núcleo en paralelo. El enfoque SMP complica al sistema operativo, ya que debe asegurar que dos
procesadores no seleccionan un mismo proceso y que no se pierde ningún proceso de la cola. Se deben emplear técnicas para resolver y sincronizar el uso de los recursos.
3.2.2 ORGANIZACIÓN SMP. La Figura 1.2 muestra la organización general de un SMP. Existen múltiples procesadores, cada uno de los cuales contiene su propia unidad de control, unidad aritmético-lógica y registros. Cada procesador tiene acceso a una memoria principal compartida y dispositivos de E/S a través de algún mecanismo de interconexión; el bus compartido es común a todos los procesadores. Los procesadores se pueden comunicar entre sí a través de la memoria (mensajes e información de estado dejados en espacios de memoria compartidos). Los procesadores han de poder intercambiarse señales directamente. A menudo la memoria está organizada de tal manera que se pueden realizar múltiples accesos simultáneos a bloques separados. En máquinas modernas, los procesadores suelen tener al menos un nivel de memoria cache, que es privada para el procesador. El uso de esta cache introduce nuevas consideraciones de
diseño. Debido a que la cache local contiene la imagen de una porción de memoria principal, si se altera una palabra en una cache, se podría invalidar una palabra en el resto de las caches. Para prevenir esto, el resto de los procesadores deben ser alertados de que se ha llevado a cabo una actualización. Este problema se conoce como el problema de coherencia de caches y se suele solucionar con técnicas hardware más que con el sistema operativo
3.2.3 CONSIDERACIONES
DE
DISEÑO
DE
SISTEMAS
OPERATIVOS
MULTIPROCESADOR. Un sistema operativo SMP gestiona los procesadores y otros recursos del computador, de manera que el usuario puede ver al sistema de la misma forma que si fuera un sistema uniprocesador multiprogramado. Un usuario puede desarrollar aplicaciones que utilicen múltiples procesos o múltiples hilos dentro de procesos sin preocuparse de sí estará disponible un único procesador o múltiples procesadores. De esta forma, un sistema operativo multiprocesador debe proporcionar toda la funcionalidad de un sistema multiprogramado, además de características adicionales para adecuarse a múltiples procesadores. Las principales claves de diseño incluyen las siguientes características: • Procesos o hilos simultáneos concurrentes. Las rutinas del núcleo necesitan ser reentrantes para permitir que varios procesadores ejecuten el mismo código del núcleo simultáneamente. Debido a que múltiples procesadores pueden ejecutar la misma o diferentes partes del código del núcleo, las tablas y la gestión de las estructuras del núcleo deben ser gestionas apropiadamente para impedir interbloqueos u operaciones inválidas. • Planificación. La planificación se puede realizar por cualquier procesador, por lo que se deben evitar los conflictos. Si se utiliza multihilo a nivel de núcleo, existe la posibilidad de planificar múltiples hilos del mismo proceso simultáneamente en múltiples procesadores. Sincronización. Con múltiples procesos activos, que pueden acceder a espacios de direcciones compartidas o recursos compartidos de E/S, se debe tener cuidado en proporcionar una sincronización eficaz. La sincronización es un servicio que fuerza la exclusión mutua y el orden de los eventos. Un mecanismo común de sincronización en los sistemas operativos multiprocesador son los cerrojos. • Gestión de memoria. La gestión de memoria en un multiprocesador debe tratar con todos los aspectos encontrados en las máquinas uniprocesador. Además, el sistema operativo necesita explotar el paralelismo hardware existente, como las memorias multipuerto, para lograr el mejor rendimiento. Los mecanismos de paginación de los diferentes procesadores deben estar coordinados para asegurar la consistencia cuando varios procesadores comparten una página o segmento y para decidir sobre el reemplazo de una página.
• Fiabilidad y tolerancia a fallos. El sistema operativo no se debe degradar en caso de fallo de un procesador. El planificador y otras partes del sistema operativo deben darse cuenta de la pérdida de un procesador y reestructurar las tablas de gestión apropiadamente. Debido a que los aspectos de diseño de un sistema operativo multiprocesador suelen ser extensiones a soluciones de problemas de diseño de uniprocesadores multiprogramados. 3.3
MICRONÚCLEO
¿Qué es un micro Núcleo? Para conocer de manera correcta que es un micro núcleo primero debemos saber dos puntos muy importantes: 1.
Modos de operación del procesador.
2.
Modelos del kernel
Modos de operación del procesador Para entender los modelos de diseño de los sistemas operativos, tenemos que hacer referencia a los modos de ejecución del procesador. El modo de ejecución del procesador indica qué conjunto de instrucciones y a qué recursos del procesador se puede acceder en un cierto instante de tiempo. En la actualidad, un procesador ofrece como mínimo dos modos de operación (ejecución) que son:
Modo privilegiado (supervisor), que permite la ejecución de todo el conjunto de
instrucciones que ofrece el procesador (no tiene ninguna relación con el modo "root" o administrador de algunos sistemas operativos).
Modo no privilegiado (usuario), que tiene algunas restricciones de acceso a aspectos
del procesador o de ejecución de instrucciones. ¿Qué es un modelo de kernel? El núcleo del sistema operativo, también conocido por la terminología inglesa kernel, es la parte más esencial del sistema operativo. Se trata de la capa visible del software más baja del sistema que provee y gestiona los recursos del sistema de forma segura a través de las llamadas al sistema. El núcleo de un sistema operativo suele operar en modo privilegiado. Al operar en dicho modo un error de programación en el núcleo del sistema operativo puede resultar en un error fatal del cual el sistema sólo puede recuperarse mediante el reinicio del sistema.
Definición de micro núcleo: Un concepto que últimamente está recibiendo mucha atención es el de micronúcleo. Un micronúcleo es la pequeña parte central de un sistema operativo que proporciona las bases para extensiones modulares. Sin embargo, el término es algo confuso, y hay varias cuestiones relacionadas con los micronúcleos con respuestas distintas por parte de diferentes equipos de diseño de sistemas operativos. Estas cuestiones incluyen, cómo de pequeño debe ser un núcleo para denominarse micronúcleo, cómo diseñar manejadores de dispositivos para obtener el mejor rendimiento a la vez que se abstraen sus funciones del hardware, si ejecutar operaciones que no pertenecen al núcleo dentro de éste o en el espacio de usuario, y si mantener el código de subsistemas existentes (por ejemplo, una versión de UNIX) o empezar de cero. El enfoque de micronúcleo se popularizó por su uso en el sistema operativo Mach. En teoría este enfoque proporciona un alto grado de flexibilidad y modularidad. Determinados productos ya tienen implementaciones micronúcleo, y este enfoque general de diseño se verá en la mayor parte de los computadores personales, estaciones de trabajo, y sistemas operativos servidor que se desarrollen en un futuro cercano. ARQUITECTURA MICRONÚCLEO Los primeros sistemas operativos desarrollados a mediados y finales de los años 50 fueron diseñados sin preocuparse por su arquitectura. Nadie tenía la experiencia necesaria en construcción de sistemas software realmente grande, y los problemas causados por la dependencia mutua e interacción no se tenían en cuenta. En estos sistemas operativos monolíticos, de prácticamente cualquier procedimiento se podía llamar a cualquier otro. Esta falta de estructura se hizo insostenible a medida que los sistemas operativos crecieron hasta proporciones desmesuradas. Por ejemplo, la primera versión de OS/360 contenía más de un millón de líneas del código; Multics, desarrollado más tarde, creció hasta 20 millones de líneas del código [DENN84]. se necesitaron técnicas de programación modular para manejar esta escala de desarrollo software. Específicamente, se desarrollaron los sistemas operativos por capas7 (Figura 1.3a), en los cuales las funciones se organizan jerárquicamente y sólo hay interacción entre las capas adyacentes. Con el enfoque por capas, la mayor parte o todas las capas ejecutan en modo núcleo.
Los problemas permanecen incluso en el enfoque por capas. Cada capa posee demasiada funcionalidad y grandes cambios en una capa pueden tener numerosos efectos, muchos difíciles de seguir, en el código de las capas adyacentes (encima o debajo). Como resultado es difícil implementar versiones a medida del sistema operativo básico con algunas funciones añadidas o eliminadas. Además, es difícil construir la seguridad porque hay muchas interacciones entre capas adyacentes.
La arquitectura del micronúcleo reemplaza la tradicional estructura vertical y estratificada en capas por una horizontal (Figura 1.3b). Los componentes del sistema operativo externos al micronúcleo se implementan como servidores de procesos; interactúan entre ellos dos a dos, normalmente por paso de mensajes a través del micronúcleo. De esta forma, el micronúcleo funciona como un intercambiador de mensajes: válida mensajes, los pasa entre los componentes, y concede el acceso al hardware. El micronúcleo también realiza una función de protección; previene el paso de mensajes a no ser que el intercambio esté permitido. Ejemplos de sist. Operativos que usan micronúcleos.
AIX
L4
AmigaOS
Netkernel
Amoeba
RaOS
Minix
RadiOS
Hurd
ChorusOS
MorphOS
QNX
NeXTSTEP (algunos lo consideran
SO3
un núcleo híbrido)
Symbian
SymbOS
RENDIMIENTO DEL MICRONÚCLEO Una potencial desventaja que se cita a menudo de los micronúcleos es la del rendimiento. Lleva más tiempo construir y enviar un mensaje a través del micronúcleo, y aceptar y decodificar la respuesta, que hacer una simple llamada a un servicio. Sin embargo, también son importantes otros factores, de forma que es difícil generalizar sobre la desventaja del rendimiento, si es que la hay. Hay mucho que depende del tamaño y de la funcionalidad del micronúcleo. [LIED96a] resume un número de estudios que revelan una pérdida sustancial del rendimiento en los que pueden ser denominados micronúcleos de primera generación. Estas pérdidas continúan a pesar de los esfuerzos realizados para optimizar el código del micronúcleo. Una respuesta a este problema fue hacer mayores los micronúcleos, volviendo a introducir servicios críticos y manejadores en el sistema operativo. Los primeros ejemplos de este enfoque son Mach y Chorus. Incrementando de forma selectiva la funcionalidad del micronúcleo se reduce el número de cambios de modo usuario-núcleo y el número de cambios de espacio de direcciones de proceso. Sin embargo, esta solución reduce los problemas de rendimiento sacrificando la fortaleza del diseño del micronúcleo: mínimas interfaces, flexibilidad, etc. Otro enfoque consiste en hacer el micronúcleo, no más grande, sino más pequeño. [LIED96b] argumenta que, apropiadamente diseñado, un micronúcleo muy pequeño elimina las pérdidas de rendimiento y mejora la flexibilidad y fiabilidad. Para dar una idea de estos tamaños, el típico micronúcleo de primera generación tenía 300 Kbytes de código y 140 interfaces de llamadas al sistema. Un ejemplo de un micronúcleo pequeño de segunda generación es el L4 [HART97, LIED95], que consiste en 12 Kbytes de código y 7 llamadas al sistema. Las experimentaciones realizadas en estos sistemas indican que pueden funcionar tan bien o mejor que sistemas operativos por capas como por ejemplo, UNIX.