• No se han encontrado resultados

El kernel Sistemas monolíticos, microkernel e híbridos

Por poco que haya usted leído u oído sobre sistemas operativos alguna vez habrá encontrado la palabra «kernel»53. En este documento ya ha aparecido dos veces, en las páginas 16 y 21.

A veces se dice que el kernel es «la parte del sistema que siempre está en la memoria principal». Pero esto no es cierto: hay componentes (módulos) que pueden formar parte del kernel, como los gestores de dispositivos que se cargan sólo si son necesarios; además, hay procesos, como la mayoría de los demonios, que están siempre en la memoria y no son del kernel.

Otra definición incorrecta, por parcial, es: «la parte del sistema operativo que define una API para los programas de aplicación y algunos programas del sistema, con una interfaz para los gestores de dispositivos». Es parcial porque sólo incluye a los que se llaman «sistemas monolíticos».

53Puede traducirse (y en algunos documentos se hace) por «núcleo». Pero el término «kernel» está tan extendido que pasa lo mismo que con «cache» (nota 9, página 24): el empeño en mantener un purismo lingüístico no debe dificultar la comprensión.

Más correcta, pero imprecisa, es la definición del FOLDOC: «la parte esencial de Unix o de otros sistemas operativos, responsable de la asignación de recursos, interfaces del hardware en bajo nivel, seguridad, etc.»

Se puede definir de una manera mucho más precisa diciendo, simplemente: kernel:el conjunto de programas que se ejecutan en modo supervisor.

Por eso no hemos hablado hasta ahora de «kernel»: hacía falta entender bien lo que significa «modo supervisor», también llamado modo kernel.

kernels monolíticos

En un kernel monolítico todos los subsistemas del sistema operativo funcionan en modo supervisor, con las interrupciones inhibidas. Realmente, desde que al principio del apartado 2.4 dijimos que íbamos a concretar con sistemas monolíticos, podríamos haber sustituido «sistema operativo» por «kernel».

La mayoría de los sistemas de tipo Unix tienen, en principio, un diseño monolítico. Su implemen- tación es un programa binario único (salvo los módulos, que ahora comentaremos) que da lugar a un único proceso con un único espacio de direccionamiento. Esto implica que, como las interrupciones están inhibidas durante este proceso único, hasta que no completa el servicio de una no puede ejecu- tarse ningún otro proceso. Se dice que es un kernel no apropiativo (página 62), en el sentido de que ninguna de sus tareas puede interrumpir a otra; obviamente, si el planificador lo permite, el kernel da un servicio apropiativo: puede suspender a los procesos que se ejecutan en modo usuario. En las apli- caciones de tiempo real este modo de funcionamiento no es admisible, porque ciertas tareas del kernel pueden tardar un tiempo excesivo. Muchos sistemas se han modificado para que estas tareas puedan interrumpirse, resultando así un kernel apropiativo.

La memoria en un sistema monolítico queda dividida en dos grandes zonas: • El espacio del kernel, donde está cargado el programa binario que lo forma. • El espacio de usuario, donde se cargan los demás programas.

El kernel tiene acceso a toda la memoria cambiando los contenidos de su tabla de páginas (figu- ra 2.20), cosa que no pueden hacer los procesos de usuario: no tienen acceso al espacio del kernel, y un intento de acceso a la MMU en modo usuario provoca una interrupción.

llamadas al sistema reconocimiento y otras interrupciones rutinas de utilidad gestores SGM SGP SGF

Figura 2.30:Estructura de un kernel monolítico. La implementación típica de un sistema monolíti-

co tiene poca estructura. Un subprograma, el que, jun- to con los gestores de periféricos, está más cercano al hardware y se suele programar en lenguaje ensambla- dor, reconoce las interrupciones y activa a uno de los subsistemas (gestión de procesos, gestión de memoria, gestión de ficheros o gestión de periféricos). Hay ruti- nas con funciones comunes (manejo de colas, de tablas, etc.) de las que pueden hacer uso todos los subsistemas (figura 2.30). Tiene la ventaja, con respecto a otras im- plementaciones que veremos, de ser eficiente: una vez que se entra en el kernel todas las operaciones nece- sarias para satisfacer la demanda se ejecutan sin salir de él y las comunicaciones entre las partes son mucho más rápidas. Pero a medida que las funciones propor-

cionadas por el kernel aumentan crece la dificultad de implementar el sistema sin caer en problemas provocados por inconsistencias e interacciones indeseadas entre unos componentes y otros.

hw gestión de procesos gestión de memoria gestión de entrada/salida gestión de ficheros procesos de usuario

Figura 2.31:Estructura en capas.

Una propuesta de diseño estructurado, ya an- tigua (1968) pero origen de muchas innovaciones posteriores, fue el sistema THE de Dijkstra, dise- ñado en la Technische Hogeschool Eindhoven, que luego se adoptó en Multics (Multiplexed In- formation and Computing Service), precursor de Unix. La idea es estructurar el sistema en capas (figura 2.31). Cada capa se implementa utilizan- do exclusivamente las facilidades proporcionadas por las capas inferiores, de manera que en cada capa quedan ocultos los detalles de su implemen- tación, como los procedimientos y estructuras de datos que utiliza. Así, cuando un proceso de usuario solicita una operación sobre un fichero con una llamada al sistema, es la capa de gestión de ficheros la que se ocupa de pasarla a la siguiente, la de gestión de periféricos. Pero ésta no actúa inmediatamente: debe pasarla a la de gestión de memoria que a su vez la pasa a la que se ocupa de la planificación, y ésta al hardware.

Seguramente esto le recuerda algo: es similar a la idea que se aplica (con más éxito) en las redes de datos, con las capas de protocolos que usted ha estudiado en la asignatura «Redes de comunicaciones». El motivo de que no se haya seguido tan fielmente en los sistemas operativos es la eficiencia: cada paso de una capa a la otra tiene un tiempo de ejecución, lo que implica al final retardos considerables en el tratamiento de las llamadas. Pero la idea de la modularidad se ha aplicado de otras formas.

Sistemas modulares

Gran parte de los componentes incluidos en un sistema operativo sólo se utilizan para un hardware determinado. Esto es especialmente cierto en el caso de los gestores de periféricos. Como son muchos los periféricos susceptibles de utilizarse, el kernel tiene que incluir a todos. Por ejemplo, hay docenas de controladores de gráficos diferentes, y para cada uno hace falta un gestor. Pero en una instalación sólo se utiliza uno de estos controladores. Lo mismo puede decirse de los discos, las impresoras, las tarjetas de red...54 Si el kernel monolítico se implementa incluyendo todos estos componentes en un único programa binario se está utilizando sin necesidad mucho espacio de memoria.

Casi todas las implementaciones actuales de Unix siguen una idea más razonable: los componentes que, aun formando parte del kernel, pueden necesitarse en unas ocasiones pero no en otras, son pro- gramas ejecutables independientes, llamados módulos. El programa ejecutable principal sólo incluye las funcionalidades esenciales: gestión de procesos, de memoria y de ficheros. Los módulos se cargan bien en el arranque o bien dinámicamente durante la ejecución, cuando son necesarios. Incluso esas funcionalidades esenciales pueden también «modularizarse». Por ejemplo, para la gestión de procesos puede haber módulos que implementen distintos algoritmos de planificación de modo que se pueda cargar en la inicialización uno u otro. Otro ejemplo es la gestión de ficheros: el kernel puede reconocer y tratar con varios sistemas de ficheros (página 48); los detalles del procesamiento para cada sistema de ficheros se programan en módulos, y lo que se incluye en el programa principal es una funciona- lidad genérica que se llama VFS (Virtual Filesystem Switch) que si, por ejemplo, se inserta un CD, automáticamente carga el módulo correspondiente al sistema de ficheros, ISO 9660.

Otra ventaja del enfoque modular es su flexibilidad para añadir a la máquina un periférico para el

54De ahí que en los programas fuente del kernel los gestores (drivers) representen más del 50 % de líneas de código, como vimos en la nota 38, página 52.

que no hay previsto un gestor: ese gestor se puede programar y compilar como módulo sin necesidad de volver a compilar todo el kernel.

Por todo esto, el antiguo debate entre los partidarios del kernel monolítico y los del microkernel55 está prácticamente superado, al menos en la situación actual.

Microkernels

El hecho de que un kernel tenga módulos que se cargan dinámicamente y no sea un único programa ejecutable no implica que deje de ser un kernel monolítico, puesto que todo se ejecuta en modo kernel56. Contrastando con el diseño monolítico, el principio del microkernel es reducir al mínimo las partes que se ejecutan en modo supervisor57.

La gestión de ficheros, la implementación de la comunicación entre procesos de usuario (IPC), los gestores, se llaman «servidores» y se ejecutan como procesos en modo usuario. La función principal del microkernelse reduce al reconocimiento de interrupciones, a gestionar la memoria, y a proporcionar unos mecanismos básicos de planificación y de comunicación entre los servidores y los programas de aplicación (clientes) (figura 2.32).

IPC programas de sistema de ficheros gestores de periféricos gestión de planificación IPC básico aplicación memoria kernel modo usuario modo mensajes microkernel

Figura 2.32:Estructura de un microkernel.

Como los servidores se ejecutan en procesos independientes, no es posible la comunicación directa ni por memoria compartida con ellos ni entre ellos, como se hace en un kernel monolítico. La comu- nicación se establece mediante paso de mensajes. Por ejemplo, si un cliente pide acceder a un fichero tiene que interactuar con el servidor de ficheros, pero no lo hace directamente, sino a través de mensajes con el microkernel. Esto tiene como consecuencia que el sistema es menos eficiente.

Sin embargo, los microkernels son más robustos: si un componente falla no falla todo el sistema, como sí puede ocurrir en un kernel monolítico.

El enfoque de microkernel es un caso claro de aplicación del principio de separación entre política y mecanismo (página 41). Los componentes que forman el microkernel proporcionan mecanismos básicos sobre los cuales se pueden implementar distintas políticas de asignación de recursos.

55Hay un documento histórico de lectura interesante: el intercambio de mensajes en 1992 entre Linus Torvals, a la sa- zón estudiante en la Universidad de Helsinki, y Andrew Tanenbaum, prestigioso profesor de la Universidad Libre (Vrije Universiteit) de Amsterdam y defensor del enfoque microkernel, que opinaba que Linux tenía un diseño «obsoleto»: http://oreilly.com/catalog/opensources/book/appa.html.

56Al ser Linux un sistema modular con esas características (salvo por algunas excepciones, como módulos en espacio de usuario) no tiene sentido decir «el kernel de Linux»: Linux es un kernel.

Sistemas híbridos

Actualmente pocos sistemas son estrictamente monolíticos o estrictamente microkernel. Los dise- ñadores tratan de combinar las ventajas de los primeros (respuesta más eficaz al basarse en memoria compartida en el espacio del kernel y no en mensajes) con las de los segundos (mayor modularidad y robustez). La figura 2.33 ilustra la esencia de las diferencias generales entre los tres enfoques.

Figura 2.33:Kernel monolítico, microkernel e híbrido

Fuente:http://en.wikipedia.org/wiki/Image:OS-structure.svg.

Ejemplos de sistemas híbridos son Windows NT y XNU («X is Not Unix»), que es el kernel de Apple para los sistemas operativos OS X y iOS. Incluso en sistemas tradicionalmente monolíticos, como Linux, freeBSD y Solaris, ciertas funcionalidades se pueden implementar como módulos que se ejecutan en el espacio de usuario. Por ejemplo, FUSE (Filesystem in Userspace) es un módulo que permite implementar sistemas de ficheros virtuales en modo usuario.

Representación de datos textuales

Relacionados con el Tema 2 de la asignatura, la Guía de Aprendizaje establece estos resultados: • Conocer los convenios de representación binaria, transmisión y almacenamiento de datos textua-

les, numéricos y multimedia.

• Conocer los principios de los algoritmos de detección de errores y de compresión.

En este capítulo veremos los convenios de representación de textos, en el capítulo 4 los de datos numéricos, y en el capítulo 5 los de datos multimedia. La detección de errores y la compresión se tratan en el capítulo 6. El capítulo 7 se dedica a los convenios de almacenamiento de los datos en ficheros.

Si vamos a tratar de «representación de textos» hay que empezar precisando qué es lo que queremos representar. Lo más sencillo es el texto plano: el formado por secuencias de grafemas (a los que, más familiarmente, llamamos caracteres), haciendo abstracción de su tamaño, color, tipo de letra, etcétera (que dan lugar a los alógrafos del grafema). Los grafemas son los caracteres visibles, pero el texto plano incluye también caracteres que no tienen una expresión gráfica y son importantes: espacio, tabulador, nueva línea, etcétera.

Empezaremos con la representación del texto plano. Para los distintos alógrafos los programas de procesamiento de textos utilizan convenios propios y muy variados (apartado 3.6), pero para el texto plano veremos que hay un número reducido de estándares. Y terminaremos el capítulo comentando una extensión de la representación textual muy importante en telemática: el hipertexto.