Micronúcleo

Ajustar Compartir Imprimir Citar
Kernel que proporciona menos servicios que un núcleo tradicional
Estructura de los sistemas operativos monolíticos y basados en microcarneles, respectivamente

En informática, un microkernel (a menudo abreviado como μ-kernel) es la cantidad casi mínima de software que puede proporcionar los mecanismos necesarios para implementar un sistema operativo. (SO). Estos mecanismos incluyen la gestión del espacio de direcciones de bajo nivel, la gestión de subprocesos y la comunicación entre procesos (IPC).

Si el hardware proporciona múltiples anillos o modos de CPU, el microkernel puede ser el único software que se ejecuta en el nivel más privilegiado, que generalmente se conoce como modo supervisor o kernel. Las funciones tradicionales del sistema operativo, como los controladores de dispositivos, las pilas de protocolos y los sistemas de archivos, generalmente se eliminan del propio microkernel y, en su lugar, se ejecutan en el espacio del usuario.

En términos del tamaño del código fuente, los micronúcleos suelen ser más pequeños que los núcleos monolíticos. El microkernel MINIX 3, por ejemplo, tiene solo aproximadamente 12 000 líneas de código.

Historia

Los micronúcleos se remontan al pionero informático danés Per Brinch Hansen y su mandato en la empresa informática danesa Regnecentralen, donde dirigió los esfuerzos de desarrollo de software para la computadora RC 4000. En 1967, Regnecentralen estaba instalando un prototipo RC 4000 en la planta de fertilizantes de Zakłady Azotowe Puławy en Polonia. La computadora usaba un pequeño sistema operativo en tiempo real diseñado para las necesidades de la planta. Brinch Hansen y su equipo se preocuparon por la falta de generalidad y reutilización del sistema RC 4000. Temían que cada instalación requiriera un sistema operativo diferente, por lo que comenzaron a investigar formas novedosas y más generales de crear software para el RC 4000. En 1969, su esfuerzo dio como resultado la finalización del sistema de programación múltiple RC 4000. Su núcleo proporcionó comunicación entre procesos basada en el paso de mensajes para hasta 23 procesos sin privilegios, de los cuales 8 a la vez estaban protegidos entre sí. Además, implementó la programación de segmentos de tiempo de programas ejecutados en paralelo, el inicio y el control de la ejecución del programa a pedido de otros programas en ejecución y el inicio de transferencias de datos hacia o desde periféricos. Además de estos mecanismos elementales, no tenía una estrategia incorporada para la ejecución del programa y la asignación de recursos. Esta estrategia iba a ser implementada por una jerarquía de programas en ejecución en la que los procesos principales tenían control total sobre los procesos secundarios y actuaban como sus sistemas operativos.

Siguiendo el trabajo de Brinch Hansen, los micronúcleos se han desarrollado desde la década de 1970. El término microkernel en sí mismo apareció por primera vez no más tarde de 1981. Los microkernels se concibieron como una respuesta a los cambios en el mundo de la informática y a varios desafíos para adaptar los "mono-kernels" a estos nuevos sistemas. Todo el tiempo se estaban desarrollando nuevos controladores de dispositivos, pilas de protocolos, sistemas de archivos y otros sistemas de bajo nivel. Este código normalmente se ubicaba en el kernel monolítico y, por lo tanto, requería un trabajo considerable y una administración de código cuidadosa para trabajar en él. Los microkernels se desarrollaron con la idea de que todos estos servicios se implementarían como programas de espacio de usuario, como cualquier otro, lo que permitiría trabajar en ellos de forma monolítica e iniciarlos y detenerlos como cualquier otro programa. Esto no solo permitiría trabajar más fácilmente con estos servicios, sino que también separaría el código del kernel para permitir que se ajuste con precisión sin preocuparse por los efectos secundarios no deseados. Además, permitiría "desarrollar" sistemas operativos completamente nuevos. en un núcleo común, ayudando a la investigación del sistema operativo.

Los micronúcleos fueron un tema muy candente en la década de 1980 cuando se introdujeron las primeras redes de área local utilizables. El núcleo AmigaOS Exec fue un ejemplo temprano, introducido en 1986 y utilizado en una PC con relativo éxito comercial. La falta de protección de la memoria, considerada en otros aspectos una falla, permitió que este kernel tuviera un rendimiento de paso de mensajes muy alto porque no necesitaba copiar datos mientras intercambiaba mensajes entre programas de espacio de usuario.

Los mismos mecanismos que permitieron que el núcleo se distribuyera en el espacio del usuario también permitieron que el sistema se distribuyera a través de enlaces de red. Los primeros micronúcleos, en particular Mach creado por Richard Rashid, demostraron tener un rendimiento decepcionante, pero las ventajas inherentes parecían tan grandes que fue una importante línea de investigación a fines de la década de 1990. Sin embargo, durante este tiempo la velocidad de las computadoras creció mucho en relación con los sistemas de red, y las desventajas en el rendimiento llegaron a abrumar las ventajas en términos de desarrollo.

Se hicieron muchos intentos para adaptar los sistemas existentes para tener un mejor rendimiento, pero la sobrecarga siempre fue considerable y la mayoría de estos esfuerzos requerían que los programas del espacio de usuario se volvieran a mover al kernel. Para el año 2000, la mayoría de los esfuerzos del núcleo Mach a gran escala habían terminado, aunque macOS de Apple, lanzado en 2001, todavía usa un núcleo híbrido llamado XNU, que combina un núcleo Mach OSF/1 fuertemente modificado (híbrido). (kernel OSFMK 7.3) con código de BSD UNIX, y este kernel también se usa en iOS, tvOS y watchOS. Windows NT, comenzando con NT 3.1 y continuando con Windows 11, usa un diseño de kernel híbrido. A partir de 2012, GNU Hurd basado en Mach también es funcional y se incluye en las versiones de prueba de Arch Linux y Debian.

Aunque el trabajo principal en micronúcleos había terminado en gran medida, los experimentadores continuaron con el desarrollo. Desde entonces, se ha demostrado que muchos de los problemas de rendimiento de los diseños anteriores no eran una limitación fundamental del concepto, sino que se debían al deseo del diseñador de utilizar sistemas de propósito único para implementar la mayor cantidad posible de estos servicios. El uso de un enfoque más pragmático del problema, incluido el código ensamblador y la confianza en el procesador para hacer cumplir los conceptos que normalmente se admiten en el software, dio lugar a una nueva serie de micronúcleos con un rendimiento notablemente mejorado.

Los micronúcleos están estrechamente relacionados con los exonúcleos. También tienen mucho en común con los hipervisores, pero estos últimos no pretenden ser minimalistas y están especializados en admitir máquinas virtuales; el microkernel L4 frecuentemente encuentra uso en una capacidad de hipervisor.

Introducción

Los primeros núcleos de los sistemas operativos eran bastante pequeños, en parte porque la memoria de la computadora era limitada. A medida que crecía la capacidad de las computadoras, también crecía la cantidad de dispositivos que el kernel tenía que controlar. A lo largo de la historia temprana de Unix, los núcleos eran generalmente pequeños, aunque contenían varios controladores de dispositivos e implementaciones de sistemas de archivos. Cuando los espacios de direcciones aumentaron de 16 a 32 bits, el diseño del kernel ya no estaba limitado por la arquitectura del hardware y los kernels comenzaron a crecer.

La distribución de software de Berkeley (BSD) de Unix inició la era de los núcleos más grandes. Además de operar un sistema básico que consta de CPU, discos e impresoras, BSD agregó un sistema de red TCP/IP completo y una serie de dispositivos "virtuales" dispositivos que permitían que los programas existentes funcionaran de forma 'invisible' sobre la red. Este crecimiento continuó durante muchos años, dando como resultado núcleos con millones de líneas de código fuente. Como resultado de este crecimiento, los núcleos eran propensos a errores y se volvieron cada vez más difíciles de mantener.

El microkernel estaba destinado a abordar este crecimiento de kernels y las dificultades resultantes. En teoría, el diseño del micronúcleo permite una gestión más sencilla del código debido a su división en servicios de espacio de usuario. Esto también permite una mayor seguridad y estabilidad como resultado de la cantidad reducida de código que se ejecuta en modo kernel. Por ejemplo, si un servicio de red falla debido a un desbordamiento del búfer, solo la memoria del servicio de red se corromperá y el resto del sistema seguirá funcionando.

Comunicación entre procesos

La comunicación entre procesos (IPC) es cualquier mecanismo que permite que procesos separados se comuniquen entre sí, generalmente mediante el envío de mensajes. La memoria compartida es, estrictamente definida, también un mecanismo de comunicación entre procesos, pero la abreviatura IPC generalmente se refiere solo al paso de mensajes, y es este último el que es particularmente relevante para los micronúcleos. IPC permite que el sistema operativo se construya a partir de una serie de programas más pequeños llamados servidores, que son utilizados por otros programas en el sistema, invocados a través de IPC. La mayoría o todo el soporte para hardware periférico se maneja de esta manera, con servidores para controladores de dispositivos, pilas de protocolos de red, sistemas de archivos, gráficos, etc.

IPC puede ser síncrono o asíncrono. IPC asíncrono es análogo a la comunicación de red: el remitente envía un mensaje y continúa ejecutándose. El receptor comprueba (sondea) la disponibilidad del mensaje o recibe una alerta a través de algún mecanismo de notificación. El IPC asíncrono requiere que el núcleo mantenga búferes y colas para mensajes, y se ocupe de los desbordamientos de búfer; también requiere copia doble de mensajes (remitente a kernel y kernel a receptor). En IPC síncrono, la primera parte (emisor o receptor) bloquea hasta que la otra parte esté lista para realizar el IPC. No requiere almacenamiento en búfer ni copias múltiples, pero la cita implícita puede dificultar la programación. La mayoría de los programadores prefieren el envío asíncrono y la recepción síncrona.

Los microkernels de primera generación generalmente admitían IPC síncrono y asíncrono, y sufrían un bajo rendimiento de IPC. Jochen Liedtke asumió que el diseño y la implementación de los mecanismos de PCI eran la razón subyacente de este bajo rendimiento. En su microkernel L4, fue pionero en métodos que redujeron los costos de IPC en un orden de magnitud. Estos incluyen una llamada al sistema IPC que admite una operación de envío y recepción, lo que hace que todos los IPC sean sincrónicos y pasan la mayor cantidad de datos posible en los registros. Además, Liedtke introdujo el concepto de cambio de proceso directo, donde durante una ejecución de IPC se realiza un cambio de contexto (incompleto) desde el remitente directamente al receptor. Si, como en L4, parte o la totalidad del mensaje se pasa en los registros, esto transfiere la parte del mensaje en el registro sin ninguna copia. Además, se evita la sobrecarga de invocar el planificador; esto es especialmente beneficioso en el caso común en el que IPC se utiliza en un tipo de llamada a procedimiento remoto (RPC) por parte de un cliente que invoca un servidor. Otra optimización, llamada programación diferida, evita cruzar las colas de programación durante IPC al dejar los subprocesos que se bloquean durante IPC en la cola lista. Una vez que se invoca el planificador, mueve dichos subprocesos a la cola de espera adecuada. Como en muchos casos un subproceso se desbloquea antes de la siguiente invocación del programador, este enfoque ahorra mucho trabajo. Desde entonces, QNX y MINIX 3 han adoptado enfoques similares.

En una serie de experimentos, Chen y Bershad compararon los ciclos de memoria por instrucción (MCPI) de Ultrix monolítico con los de microkernel Mach combinado con un servidor Unix 4.3BSD que se ejecuta en el espacio del usuario. Sus resultados explicaron el rendimiento más bajo de Mach por un MCPI más alto y demostraron que IPC por sí solo no es responsable de gran parte de la sobrecarga del sistema, lo que sugiere que las optimizaciones centradas exclusivamente en IPC tendrán un efecto limitado. Más tarde, Liedtke perfeccionó los resultados de Chen y Bershad al observar que la mayor parte de la diferencia entre Ultrix y Mach MCPI se debió a fallas en la capacidad de caché y concluyó que reducir drásticamente el conjunto de trabajo de caché de un microkernel resolverá el problema.

En un sistema cliente-servidor, la mayor parte de la comunicación es esencialmente síncrona, incluso si se usan primitivas asíncronas, ya que la operación típica es un cliente que invoca un servidor y luego espera una respuesta. Como también se presta a una implementación más eficiente, la mayoría de los micronúcleos generalmente siguieron el ejemplo de L4 y solo proporcionaron una primitiva IPC síncrona. El IPC asíncrono podría implementarse en la parte superior mediante el uso de subprocesos auxiliares. Sin embargo, la experiencia ha demostrado que la utilidad del IPC síncrono es dudosa: el IPC síncrono impone un diseño de subprocesos múltiples en sistemas que de otro modo serían simples, con las complejidades de sincronización resultantes. Además, una invocación de servidor similar a RPC secuencializa el cliente y el servidor, lo que debe evitarse si se ejecutan en núcleos separados. Por lo tanto, las versiones de L4 implementadas en productos comerciales han considerado necesario agregar un mecanismo de notificación asíncrona para admitir mejor la comunicación asíncrona. Este mecanismo similar a una señal no transporta datos y, por lo tanto, no requiere almacenamiento en búfer por parte del kernel. Al tener dos formas de CIP, sin embargo, han violado el principio de minimalidad. Otras versiones de L4 han cambiado completamente a IPC asíncrono.

Como el IPC síncrono bloquea a la primera parte hasta que la otra esté lista, el uso sin restricciones podría conducir fácilmente a interbloqueos. Además, un cliente podría montar fácilmente un ataque de denegación de servicio en un servidor enviando una solicitud y nunca intentando recibir la respuesta. Por lo tanto, el IPC síncrono debe proporcionar un medio para evitar el bloqueo indefinido. Muchos micronúcleos proporcionan tiempos de espera en las llamadas IPC, lo que limita el tiempo de bloqueo. En la práctica, es difícil elegir valores de tiempo de espera sensatos, y los sistemas casi inevitablemente usan tiempos de espera infinitos para los clientes y tiempos de espera cero para los servidores. Como consecuencia, la tendencia es no proporcionar tiempos de espera arbitrarios, sino solo una bandera que indica que el IPC debe fallar inmediatamente si el socio no está listo. Este enfoque proporciona efectivamente una opción de los dos valores de tiempo de espera de cero e infinito. Las versiones recientes de L4 y MINIX han seguido este camino (las versiones anteriores de L4 usaban tiempos de espera). QNX evita el problema al requerir que el cliente especifique el búfer de respuesta como parte de la llamada de envío del mensaje. Cuando el servidor responde, el kernel copia los datos en el búfer del cliente, sin tener que esperar a que el cliente reciba la respuesta explícitamente.

Servidores

Los servidores Microkernel son esencialmente programas daemon como cualquier otro, excepto que el kernel otorga a algunos de ellos privilegios para interactuar con partes de la memoria física que, de otro modo, estarían fuera del alcance de la mayoría de los programas. Esto permite que algunos servidores, en particular los controladores de dispositivos, interactúen directamente con el hardware.

Un conjunto básico de servidores para un microkernel de uso general incluye servidores de sistemas de archivos, servidores de controladores de dispositivos, servidores de red, servidores de visualización y servidores de dispositivos de interfaz de usuario. Este conjunto de servidores (extraídos de QNX) proporciona aproximadamente el conjunto de servicios que ofrece un kernel monolítico de Unix. Los servidores necesarios se inician al iniciar el sistema y brindan servicios, como acceso a archivos, redes y dispositivos, a programas de aplicación ordinarios. Con dichos servidores ejecutándose en el entorno de una aplicación de usuario, el desarrollo del servidor es similar al desarrollo de una aplicación ordinaria, en lugar del proceso de compilación y arranque necesario para el desarrollo del kernel.

Además, muchos "bloqueos" se puede corregir simplemente deteniendo y reiniciando el servidor. Sin embargo, parte del estado del sistema se pierde con el servidor que falla, por lo que este enfoque requiere que las aplicaciones hagan frente a la falla. Un buen ejemplo es un servidor responsable de las conexiones TCP/IP: si se reinicia este servidor, las aplicaciones experimentarán un error "perdido" conexión, una ocurrencia normal en un sistema en red. Para otros servicios, la falla es menos esperada y puede requerir cambios en el código de la aplicación. Para QNX, la capacidad de reinicio se ofrece como el kit de herramientas de alta disponibilidad de QNX.

Controladores de dispositivos

Los controladores de dispositivos realizan con frecuencia acceso directo a la memoria (DMA) y, por lo tanto, pueden escribir en ubicaciones arbitrarias de la memoria física, incluidas varias estructuras de datos del kernel. Por lo tanto, se debe confiar en dichos controladores. Es un error común pensar que esto significa que deben ser parte del kernel. De hecho, un controlador no es inherentemente más o menos confiable por ser parte del kernel.

Si bien la ejecución de un controlador de dispositivo en el espacio del usuario no reduce necesariamente el daño que puede causar un controlador que se comporta mal, en la práctica es beneficioso para la estabilidad del sistema en presencia de controladores defectuosos (en lugar de maliciosos): infracciones de acceso a la memoria por parte del controlador el código en sí mismo (a diferencia del dispositivo) aún puede ser capturado por el hardware de administración de memoria. Además, muchos dispositivos no son compatibles con DMA, sus controladores pueden volverse no confiables ejecutándolos en el espacio del usuario. Recientemente, un número cada vez mayor de computadoras cuentan con IOMMU, muchas de las cuales se pueden usar para restringir el acceso de un dispositivo a la memoria física. Esto también permite que los controladores en modo usuario dejen de ser confiables.

Los controladores en modo de usuario en realidad son anteriores a los micronúcleos. Michigan Terminal System (MTS), en 1967, admitió controladores de espacio de usuario (incluido su soporte de sistema de archivos), el primer sistema operativo diseñado con esa capacidad. Históricamente, los controladores eran un problema menor, ya que la cantidad de dispositivos era pequeña y confiable de todos modos, por lo que tenerlos en el kernel simplificó el diseño y evitó posibles problemas de rendimiento. Esto condujo al estilo tradicional de controlador en el kernel de Unix, Linux y Windows NT. Con la proliferación de varios tipos de periféricos, la cantidad de código de controlador aumentó y, en los sistemas operativos modernos, domina el kernel en tamaño de código.

Componentes esenciales y minimalidad

Como un microkernel debe permitir la creación de servicios de sistema operativo arbitrarios en la parte superior, debe proporcionar alguna funcionalidad central. Como mínimo, esto incluye:

Este diseño mínimo fue iniciado por Nucleus de Brinch Hansen y el hipervisor de la máquina virtual de IBM. Desde entonces, se ha formalizado en el principio de minimalidad de Liedtke:

Un concepto se tolera dentro del microcarril solo si lo mueve fuera del núcleo, es decir, permitiendo implementaciones competitivas, evitaría la implementación de la funcionalidad requerida del sistema.

Todo lo demás se puede hacer en un programa en modo de usuario, aunque los controladores de dispositivos implementados como programas de usuario pueden requerir privilegios especiales en algunas arquitecturas de procesador para acceder al hardware de E/S.

Relacionado con el principio de minimalidad, e igualmente importante para el diseño de microkernel, está la separación de mecanismo y política, es lo que permite la construcción de sistemas arbitrarios sobre un kernel mínimo. Cualquier política integrada en el kernel no se puede sobrescribir a nivel de usuario y, por lo tanto, limita la generalidad del microkernel. La política implementada en los servidores de nivel de usuario se puede cambiar reemplazando los servidores (o dejando que la aplicación elija entre servidores de la competencia que ofrecen servicios similares).

Por motivos de eficiencia, la mayoría de los micronúcleos contienen planificadores y gestionan temporizadores, lo que infringe el principio de minimalidad y el principio de separación entre políticas y mecanismos.

La puesta en marcha (arranque) de un sistema basado en microkernel requiere controladores de dispositivo, que no forman parte del kernel. Por lo general, esto significa que están empaquetados con el kernel en la imagen de arranque, y el kernel admite un protocolo de arranque que define cómo se ubican e inician los controladores; este es el procedimiento de arranque tradicional de los micronúcleos L4. Algunos microkernels simplifican esto colocando algunos controladores clave dentro del kernel (en violación del principio de minimalidad), LynxOS y el Minix original son ejemplos. Algunos incluso incluyen un sistema de archivos en el núcleo para simplificar el arranque. Un sistema basado en microkernel puede arrancar a través de un cargador de arranque compatible con arranque múltiple. Dichos sistemas suelen cargar servidores vinculados estáticamente para realizar un arranque inicial o montar una imagen del sistema operativo para continuar con el arranque.

Un componente clave de un microkernel es un buen sistema IPC y un diseño de administrador de memoria virtual que permita implementar el manejo de fallas de página y el intercambio en servidores en modo usuario de manera segura. Dado que todos los servicios son realizados por programas en modo usuario, los medios eficientes de comunicación entre programas son esenciales, mucho más que en los núcleos monolíticos. El diseño del sistema IPC hace o deshace un microkernel. Para ser efectivo, el sistema IPC no solo debe tener una sobrecarga baja, sino que también debe interactuar bien con la programación de la CPU.

Rendimiento

En la mayoría de los procesadores principales, obtener un servicio es intrínsecamente más costoso en un sistema basado en microkernel que en un sistema monolítico. En el sistema monolítico, el servicio se obtiene mediante una sola llamada al sistema, lo que requiere dos cambios de modo (cambios del modo de anillo o CPU del procesador). En el sistema basado en microkernel, el servicio se obtiene enviando un mensaje IPC a un servidor y obteniendo el resultado en otro mensaje IPC del servidor. Esto requiere un cambio de contexto si los controladores se implementan como procesos, o una llamada de función si se implementan como procedimientos. Además, pasar datos reales al servidor y viceversa puede generar una sobrecarga de copia adicional, mientras que en un sistema monolítico el kernel puede acceder directamente a los datos en los búfer del cliente.

Por lo tanto, el rendimiento es un problema potencial en los sistemas de micronúcleo. La experiencia de los microkernels de primera generación, como Mach y ChorusOS, mostró que los sistemas basados en ellos funcionaron muy mal. Sin embargo, Jochen Liedtke demostró que los problemas de rendimiento de Mach eran el resultado de un diseño e implementación deficientes, específicamente la huella de caché excesiva de Mach. Liedtke demostró con su propio micronúcleo L4 que a través de un diseño e implementación cuidadosos, y especialmente siguiendo el principio de minimalidad, los costos de IPC podrían reducirse en más de un orden de magnitud en comparación con Mach. El rendimiento de IPC de L4 aún no ha sido superado en una variedad de arquitecturas.

Si bien estos resultados demuestran que el rendimiento deficiente de los sistemas basados en microkernels de primera generación no es representativo de los kernels de segunda generación como L4, esto no constituye una prueba de que los sistemas basados en microkernels puedan construirse con un buen rendimiento. Se ha demostrado que un servidor Linux monolítico portado a L4 exhibe solo un pequeño porcentaje de sobrecarga sobre Linux nativo. Sin embargo, un sistema de un solo servidor de este tipo exhibe pocas, si es que alguna, de las ventajas que se supone que brindan los micronúcleos al estructurar la funcionalidad del sistema operativo en servidores separados.

Existe una serie de sistemas multiservidor comerciales, en particular los sistemas en tiempo real QNX e Integrity. No se ha publicado ninguna comparación exhaustiva del rendimiento en relación con los sistemas monolíticos para esos sistemas multiservidor. Además, el rendimiento no parece ser la principal preocupación de esos sistemas comerciales, que en su lugar enfatizan tiempos de respuesta de manejo de interrupciones (QNX) rápidos y confiables y la simplicidad en aras de la robustez. Un intento de construir un sistema operativo multiservidor de alto rendimiento fue el proyecto IBM Sawmill Linux. Sin embargo, este proyecto nunca se completó.

Mientras tanto, se ha demostrado que los controladores de dispositivos a nivel de usuario pueden acercarse al rendimiento de los controladores en el kernel, incluso para dispositivos de alto rendimiento y alta interrupción como Gigabit Ethernet. Esto parece implicar que son posibles los sistemas multiservidor de alto rendimiento.

Seguridad

Los beneficios de seguridad de los micronúcleos se han discutido con frecuencia. En el contexto de la seguridad, el principio de minimalidad de los micronúcleos es, según algunos, una consecuencia directa del principio de privilegio mínimo, según el cual todo el código debe tener solo los privilegios necesarios para proporcionar la funcionalidad requerida. La minimalidad requiere que la base informática confiable (TCB) de un sistema se mantenga mínima. Dado que el kernel (el código que se ejecuta en el modo privilegiado del hardware) tiene acceso no autorizado a cualquier dato y, por lo tanto, puede violar su integridad o confidencialidad, el kernel siempre forma parte de la TCB. Minimizarlo es natural en un diseño impulsado por la seguridad.

En consecuencia, los diseños de microkernel se han utilizado para sistemas diseñados para aplicaciones de alta seguridad, incluidos KeyKOS, EROS y sistemas militares. De hecho, los criterios comunes (CC) al más alto nivel de garantía (Nivel de Garantía de Evaluación (EAL) 7) tienen un requisito explícito de que el objetivo de la evaluación sea "simple", un reconocimiento de la imposibilidad práctica de establecer una verdadera confiabilidad para un sistema complejo. Nuevamente, el término "simple" es engañoso y está mal definido. Al menos, los Criterios de Evaluación del Sistema Informático de Confianza del Departamento de Defensa introdujeron una palabrería algo más precisa en las clases B3/A1:

"El TCB completará, conceptualmente, mecanismos de protección simples con semántica definida precisamente. La ingeniería significativa del sistema se dirigirá a minimizar la complejidad del TCB, así como a excluir del TCB los módulos que no son críticos para la protección".

Criterios de evaluación del sistema informático con confianza del Departamento de Defensa

En 2018, un documento presentado en la Conferencia de sistemas de Asia y el Pacífico afirmó que los microkernels eran demostrablemente más seguros que los kernels monolíticos al investigar todos los CVE críticos publicados para el kernel de Linux en ese momento. El estudio concluyó que el 40% de los problemas no podrían ocurrir en absoluto en un microkernel formalmente verificado, y solo el 4% de los problemas permanecerían completamente sin mitigar en dicho sistema.

Tercera generación

El trabajo más reciente sobre microkernels se ha centrado en las especificaciones formales de la API del kernel y las pruebas formales de las propiedades de seguridad y la corrección de la implementación de la API. El primer ejemplo de esto es una demostración matemática de los mecanismos de confinamiento en EROS, basada en un modelo simplificado de la API de EROS. Más recientemente (en 2007) se realizó un conjunto completo de pruebas verificadas por máquina de las propiedades del modelo de protección de seL4, una versión de L4.

Esto ha llevado a lo que se conoce como microkernels de tercera generación, caracterizados por una API orientada a la seguridad con acceso a recursos controlado por capacidades, la virtualización como una preocupación de primera clase, enfoques novedosos para kernel gestión de recursos, y un objetivo de diseño de idoneidad para el análisis formal, además del objetivo habitual de alto rendimiento. Algunos ejemplos son Coyotos, seL4, Nova, Redox y Fiasco.OC.

En el caso de seL4, se logró una verificación formal completa de la implementación, es decir, una prueba matemática de que la implementación del kernel es consistente con su especificación formal. Esto proporciona una garantía de que las propiedades demostradas sobre la API realmente se mantienen para el kernel real, un grado de seguridad que va más allá incluso de CC EAL7. Le siguieron pruebas de las propiedades de cumplimiento de seguridad de la API y una prueba que demuestra que el código binario ejecutable es una traducción correcta de la implementación de C, sacando el compilador de la TCB. En conjunto, estas pruebas establecen una prueba de extremo a extremo de las propiedades de seguridad del núcleo.

Ejemplos

Algunos ejemplos de micronúcleos son:

Nanonúcleo

El término nanokernel o picokernel se refería históricamente a:

También hay al menos un caso en el que el término nanokernel no se usa para referirse a un kernel pequeño, sino a uno que admite una resolución de reloj de nanosegundos.