OSF/1 es un ejemplo de sistema operativo distribuido, compatible UNIX, y basado en el microkernel de Mach, de forma que proporciona gestión de procesos e hilos, multitarea multihilo, multiproceso simétrico y comunicación entre procesos mediante mensajes.
A continuación se presenta una breve historia de OSF/1, su arquitectura, la estructura de su núcleo y la gestión de procesos e hilos que realiza.
OSF/1 es el sistema operativo diseñado por la Open Software Foundation. La OSF se creó en 1988 como una organización no lucrativa. Su objetivo es promover la investigación y diseño de sistemas abiertos en la industria de la computación. Consta de más de 200 empresas participantes, y las áreas de investigación de OSF incluyen los sistemas operativos (OSF/1), entornos de usuario (Motif), entornos de cómputo distribuido (DCE), formato de distribución de arquitectura neutral (ANDF), y entornos de gestión distribuida (DME).
OSF/1 es el sistema operativo de la Open Software Foundation que cumple con diversos estándares, es compatible con otras versiones de UNIX, y contiene algunas características novedosas. OSF/1 ha evolucionado a partir de Mach de CMU, Berkeley UNIX 4.4BSD y UNIX System V. El kernel se basa principalmente en la tecnología de Mach, permitiendo como nueva característica la carga de gestores de dispositivo de forma dinámica. OSF/1 se basa en una modificación del kernel de Mach, para permitir el multiproceso simétrico, gestión de memoria virtual avanzada, comunicación entre procesos segura, y el uso de múltiples hilos que mejoran el rendimiento. Otras innovaciones de OSF/1 incluyen un entorno de ejecución con un cargador extensible, librerías compartidas, enlace y carga dinámicos, un sistema de ficheros virtual (VFS), un gestor de volúmenes lógicos (LVM), un sistema de seguridad del tipo C2/B1, y el cumplimiento de normas POSIX. Existe, también, un conjunto de comandos y librerías internacionalizados en el nivel superior de OSF/1.
Actualmente OSF/1 ha sido implementado por diversos fabricantes para sus distintas plataforma, entre los que destacan IBM, Digital, Hitachi, Hewlett-Packard, Intel y Siemens.
El núcleo de OSF/1 es una versión multihilo del núcleo de Mach desarrollado por CMU. El objetivo era regresar a la idea original de UNIX de kernel compacto, es decir, un microkernel que soportara múltiples capas que proporcionaran variaciones de sistemas operativos para entornos de aplicación específicos. El soporte de multiprocesadores constituyó un requisito clave, junto a la portabilidad y la escalabilidad. Las abstracciones de programación básicas incluyeron capacidades de multiproceso simétrico para aplicaciones de proceso paralelo de propósito general.
La parte de núcleo correspondiente a Mach maneja la planificación, la gestión de memoria, y la comunicación entre procesos sin grandes modificaciones respecto a la versión original de Mach. El soporte de multiproceso simétrico para UNIX se consigue empleando las abstracciones del kernel Mach : procesos, hilos, objetos de memoria, puertos y mensajes. Además OSF implementa el estándar IEEE POSIX Pthreads como paquete para el soporte de hilos. Básicamente, el proceso es un contenedor de recursos como la memoria virtual, derechos de acceso, descriptores de ficheros, etc. Cada hilo contiene un mínimo de información de estado con el objetivo de minimizar la sobrecarga debida al cambio de contexto.
Los puertos y mensajes proporcionan un método seguro y de gran rendimiento de comunicación entre procesos. Son empleados en RPC y peticiones de memoria para los usuarios. Cada puerto proporciona un canal de comunicación para los mensajes. Los puertos se implementan mediante una cola de mensajes protegida en el núcleo. Los objetos de memoria permiten gestionar la memoria virtual, lo que permite construir un sistema de paginación modular, extensible y sobre la red.
OSF/1 posee un conmutador interno de sistemas de ficheros lo que facilita la utilización de múltiples sistemas de ficheros como 4.4BSD UFS, NFS y Sys V FS.
El cargador de programas es una nueva característica desarrollada en OSF/1. Existe un formato de fichero objeto independiente, y soporta librerías compartidas. El cargador se ejecuta en el espacio de usuario:
Además, OSF/1 cumple con la norma estándar IEEE 1003.1 POSIX sobre control de sesión y posee dos niveles de seguridad, nivel C2 como control de seguridad normal y nivel B para máximo control.
Las características de Mach junto con las extensiones en OSF/1 posibilitan una eficiente comunicación entre procesos, memoria virtual compartida, ficheros mapeados en memoria, y gestión de excepciones. Mach soporta el paso de mensajes a través de puertos, y control de seguridad. Un servidor de mensajes de red puede emplearse para pasar mensajes entre procesos ejecutándose en máquinas distintas, a través de la red.
La administración de procesos e hilos en OSF/1 es básicamente la misma que la realizada por Mach, ya que el kernel de OSF/1 es básicamente el kernel Mach con algunas modificaciones. Sin embargo, con OSF/1 se proporciona un paquete de hilos de nivel usuario que cumple el estándar IEEE 1003.4a POSIX, conocido como Pthreads o POSIX Threads (es uno de los borradores del recientemente aprobado estándar IEEE 1003.1c POSIX).
Un hilo implica a un flujo de control secuencial. En los programas convencionales sólo es necesario un hilo simple. En cambio, en computadoras paralelas o sistemas distribuidos, una aplicación puede requerir múltiples hilos que se ejecutan simultáneamente. La creación de hilos es un proceso relativamente barato en términos de tiempo de ejecución y recursos de sistema operativo, por eso los sistemas modernos intentan conseguir un alto grado de hilos en ejecución paralela. Se debe tener en cuenta que todos los hilos de un proceso comparten el mismo espacio de direcciones y por tanto las variables globales, por eso el acceso a los datos debe ser sincronizado. Los hilos se crean para cooperar entre ellos en la resolución de un problema.
Incluso en sistemas monoprocesador la utilización de hilos mejora el rendimiento. Empleando Pthreads se pueden desarrollar aplicaciones multiprocesador que sean portables incluso en un sistema de un sólo procesador. Además, muchas aplicaciones pueden ejecutarse de una forma más eficiente utilizando hilos. En un forma sencilla, se puede pensar en los hilos como la capacidad de aplicar varios programas para resolver un problema común. Cada programa realiza una pequeña tarea. En una aproximación más realista, un programa simple se divide en múltiples hilos a procesar en paralelo.
Un ejemplo del uso de los hilos es la construcción de un servidor, que contiene un programa principal simple que crea un hilo para cada petición. Los hilos se pueden bloquear. Cada hilo puede esperar una entrada en un canal independiente y atender cada solicitud de servicio. Mientras algunos hilos se encuentran bloqueados, otros pueden estar ejecutándose. Las peticiones pueden ser servidas simultáneamente en un sistema multiprocesador. Otras ventajas de los hilos están relacionadas con el proceso paralelo, que permite realizar cálculos, comunicaciones y actividades de E/S de forma simultánea.
Otra razón para emplear los hilos es la gestión de eventos asíncronos eficientemente. Esto permite evitar los inconvenientes de las interrupciones y evitar complejos controles de flujo.
A continuación se presenta un ejemplo de la estructura de un servidor programado mediante hilos. El servidor multihilo funciona como un gestor que mantiene los datos en una tabla de datos en memoria. Los hilos creados comparten la tabla en memoria.
void RealizarPeticion(canal) { op = read(canal); clave = read(canal); lock(tabla); switch(op) { get: write(canal, tabla[clave]); set: tabla[clave] = read(canal); } unlock(tabla); } ************** do while (1) { //Esperar una nueva solicitud . . . //Crear e iniciar un hilo para resolver la petición ret = pthread_create(&nuevo_hilo, pthread_attr_default, RealizarPeticion, canal); }
Las solicitudes son enviadas sobre un canal de comunicación para almacenar o recuperar datos. La función RealizarPeticion corresponde al hilo que comienza su ejecución tras haber sido creado por la función pthread_create. La creación del hilo requiere una serie de atributos por defecto para las características del hilo. Cuando finaliza la función RealizarPetición, el hilo termina.
Tras haber leído una operación del canal de comunicación, se localizar el registro solicitado en la tabla. La función lock garantiza el acceso exclusivo a la tabla compartida por todos los hilos. La función unlock libera el acceso exclusivo una vez que la petición ha sido servida.
Los hilos necesitan sincronizar el acceso a una región
de datos compartida, utilizando algún método de
sincronización, como mútex (mutual exclusive,
exclusión mutua) en OSF/1. Sólo un hilo puede poseer
un mútex al mismo tiempo, el resto de hilos que intentan
adquirir el mútex son bloqueados. De esta forma, la sincronización
de hilos emplea mecanismos de espera y señalización.
Se necesitan también funciones de cancelación de
hilos. Las funciones de las librerías son llamadas empleando
el estándar POSIX 1003.4a. Los Pthreads son empleados para
mejorar el rendimiento con soporte de multiprocesador, desarrollo
cruzado y un interfaz estándar.