RTLinux
RTLinux es un micronúcleo de sistema operativo en tiempo real (RTOS) que ejecuta todo el sistema operativo Linux como un proceso totalmente preventivo. La propiedad de tiempo real permite controlar robots, sistemas de adquisición de datos, plantas de fabricación y otros instrumentos y máquinas sensibles al tiempo desde aplicaciones RTLinux. El diseño fue patentado. A pesar del nombre similar, no está relacionado con el proyecto Real-Time Linux de la Fundación Linux.
RTLinux fue desarrollado por Victor Yodaiken, Michael Barabanov, Cort Dougan y otros en el Instituto de Minería y Tecnología de Nuevo México y luego como producto comercial en FSMLabs. Wind River Systems adquirió la tecnología integrada de FSMLabs en febrero de 2007 y puso a disposición una versión como Wind River Real-Time Core para Wind River Linux. En agosto de 2011, Wind River descontinuó la línea de productos Wind River Real-Time Core, poniendo fin de manera efectiva al soporte comercial para el producto RTLinux.
Fondo
El objetivo clave del diseño de RTLinux era agregar capacidades de tiempo real a un sistema operativo básico para facilitar el desarrollo de programas de control complejos con ambas capacidades. Por ejemplo, uno podría querer desarrollar un controlador de motor en tiempo real que utilizara una base de datos de productos básicos y exportara una interfaz de operador web. En lugar de intentar construir un único sistema operativo que pudiera soportar capacidades en tiempo real y no real, RTLinux fue diseñado para compartir un dispositivo informático entre un sistema operativo en tiempo real y no real de modo que (1) el El sistema operativo en tiempo real nunca podría bloquear la ejecución del sistema operativo en tiempo no real y (2) los componentes que se ejecutan en los dos entornos diferentes podrían compartir datos fácilmente. Como su nombre lo indica, RTLinux fue diseñado originalmente para usar Linux como sistema no en tiempo real, pero eventualmente evolucionó para que el kernel en tiempo real RTCore pudiera ejecutarse con Linux o Berkeley Software Distribution (BSD) Unix.
Multi-Environment Real-Time (MERT) fue el primer ejemplo de un sistema operativo en tiempo real que coexiste con un sistema Unix. MERT se basó en técnicas de virtualización tradicionales: el kernel en tiempo real era el sistema operativo host (o hipervisor) y Bell Systems Unix era el invitado. RTLinux fue un intento de actualizar el concepto MERT a la era de las PC y al hardware básico. También fue un intento de superar los límites de rendimiento de MERT, en particular la sobrecarga introducida por la virtualización.
En lugar de encapsular el sistema operativo invitado en una máquina virtual, RTLinux virtualizó solo el control de interrupciones del invitado. Este método permitió al kernel en tiempo real convertir el sistema operativo invitado en un sistema completamente interrumpible pero que aún podía controlar directamente, por ejemplo, los dispositivos de almacenamiento. En particular, los controladores estándar para el huésped funcionaban sin modificar el código fuente, aunque era necesario volver a compilarlos para utilizar los "ganchos" de virtualización. Véase también paravirtualización. El pipe de Unix se adaptó para permitir la comunicación de programas en tiempo real y no real, aunque también se agregaron otros métodos, como la memoria compartida.
Desde el punto de vista del programador, RTLinux originalmente parecía un pequeño entorno de subprocesos para tareas en tiempo real más el entorno estándar de Linux para todo lo demás. El sistema operativo en tiempo real se implementó como un módulo de kernel cargable que comenzó virtualizando el control de interrupciones de los invitados y luego inició un programador en tiempo real. A las tareas se les asignaron prioridades estáticas y la programación originalmente se basaba exclusivamente en prioridades. El sistema operativo invitado se incorporó como la tarea de menor prioridad y esencialmente actuó como tarea inactiva para el sistema en tiempo real. Las tareas en tiempo real se ejecutaron en modo kernel. El desarrollo posterior de RTLinux adoptó la interfaz de programación de aplicaciones (API) de subprocesos POSIX de la interfaz de sistema operativo portátil (POSIX) y luego permitió la creación de subprocesos en modo de usuario con subprocesos en tiempo real ejecutándose dentro de procesos invitados. En entornos multiprocesador, los subprocesos estaban bloqueados en los núcleos del procesador y era posible evitar que el subproceso invitado se ejecutara en el núcleo designado (reservando efectivamente los núcleos solo para el procesamiento en tiempo real).
Implementación
RTLinux proporciona la capacidad de ejecutar tareas especiales en tiempo real y controladores de interrupciones en la misma máquina que Linux estándar. Estas tareas y controladores se ejecutan cuando es necesario, sin importar lo que esté haciendo Linux. El peor de los casos entre el momento en que el procesador detecta una interrupción de hardware y el momento en que comienza a ejecutarse un controlador de interrupciones es inferior a 15 microsegundos en RTLinux ejecutándose en un x86 genérico (alrededor de 2000). Una tarea periódica de RTLinux se ejecuta dentro de los 35 microsegundos de su tiempo programado en el mismo hardware. Estos tiempos están limitados por el hardware y, a medida que el hardware mejore, RTLinux también mejorará. Linux estándar tiene un rendimiento promedio excelente e incluso puede proporcionar una precisión de programación a nivel de milisegundos para tareas que utilizan las capacidades suaves en tiempo real de POSIX. Sin embargo, Linux estándar no está diseñado para proporcionar una precisión inferior a un milisegundo y garantías de sincronización confiables. RTLinux se basó en una máquina virtual liviana donde el servidor "invitado" recibió un controlador de interrupción virtualizado y un temporizador, y todos los demás accesos al hardware fueron directos. Desde el punto de vista del "host" en tiempo real, el kernel de Linux es un hilo. Las interrupciones necesarias para el procesamiento determinista son procesadas por el núcleo en tiempo real, mientras que otras interrupciones se reenvían a Linux, que se ejecuta con menor prioridad que los subprocesos en tiempo real. Los controladores de Linux manejaron casi todas las E/S. Se pueden utilizar canalizaciones de primero en entrar, primero en salir (FIFO) o memoria compartida para compartir datos entre el sistema operativo y RTLinux.
Objetivo
El objetivo clave del diseño de RTLinux es que el sistema sea transparente, modular y extensible. Transparencia significa que no hay cajas negras que no se puedan abrir y que el coste de cualquier operación debe ser determinable. Modularidad significa que es posible omitir la funcionalidad y el costo de esa funcionalidad si no es necesaria. Y la extensibilidad significa que los programadores deberían poder agregar módulos y adaptar el sistema a sus requisitos. El sistema RTLinux básico admite el manejo de interrupciones de alta velocidad y nada más. Tiene un programador de prioridades simple que puede ser reemplazado fácilmente por programadores más adecuados a las necesidades de alguna aplicación específica. Al desarrollar RTLinux, se diseñó para maximizar la ventaja que obtenemos al tener Linux y sus poderosas capacidades disponibles.
Componentes principales
RTLinux está estructurado como un pequeño componente central y un conjunto de componentes opcionales. El componente central permite la instalación de controladores de interrupciones de muy baja latencia que el propio Linux no puede retrasar ni adelantar y algunas rutinas de control de interrupciones y sincronización de bajo nivel. Este componente central se ha ampliado para admitir SMP y, al mismo tiempo, se ha simplificado eliminando algunas funciones que se pueden proporcionar fuera del núcleo.
Funciones
La mayoría de las funciones de RTLinux se encuentran en un conjunto de módulos del kernel cargables que proporcionan servicios opcionales y niveles de abstracción. Estos módulos incluyen:
- rtl sched - un programador prioritario que soporta tanto una interfaz "lite POSIX" descrita a continuación y la API original V1 RTLinux.
- rtl time - que controla los relojes del procesador y exporta una interfaz abstracta para conectar los manipuladores a los relojes.
- rtl posixio - soporta el estilo POSIX read/write/open interfaz a los controladores de dispositivo.
- rtl fifo - conecta tareas RT e interrumpe los controladores a procesos Linux a través de una capa de dispositivo para que los procesos Linux puedan leer y escribir a componentes RT.
- semáforo - un paquete contribuido por Jerry Epplin que da tareas RT bloqueando semáforos.
- POSIX apoyo mutex está previsto estar disponible en la próxima actualización de versión menor de RTLinux.
- mbuff es un paquete contribuido escrito por Tomasz Motylewski para proporcionar memoria compartida entre componentes RT y procesos Linux.
Real Time tasks
Las tareas en tiempo real de RTLinux se implementan como módulos del kernel similares al tipo de módulo que Linux utiliza para controladores, sistemas de archivos, etc. Las tareas en tiempo real tienen acceso directo al hardware y no utilizan memoria virtual. Durante la inicialización, una tarea (módulo) en tiempo real informa al núcleo RTLinux de sus restricciones de fecha límite, período y tiempo de lanzamiento.
Hilos
RT-Linux implementa una API POSIX para la manipulación de subprocesos. Un hilo se crea llamando a la función pthread_create
. El tercer parámetro de pthread_create
es una función que contiene el código ejecutado por el hilo.
Es necesario establecer prioridades de subprocesos en RTLinux. Los subprocesos con prioridades más altas pueden adelantarse a los subprocesos con prioridades más bajas. Por ejemplo, podemos tener un hilo controlando un motor paso a paso. Para mover el motor con fluidez, es necesario iniciar esta rosca a intervalos estrictamente regulares. Esto se puede garantizar asignando una alta prioridad a este hilo. El ejemplo threads2.c establece diferentes prioridades de subprocesos. La configuración de la prioridad del hilo se realiza mediante el código que se muestra a continuación:
int init_module()vacío){}pthread_attr_t attr;struct sched_param param;pthread_attr_init()"attr);param.sched_priority = 1;pthread_attr_setschedparam()"attr, "param);pthread_create()"t1, "attr, "thread_code, "Este es el hilo 1");rtl_printf()"El texto 1 comenzón");...}
El resultado del programa es el siguiente.
Thread 1 started Thread 2 started Thread 3 started Mensaje: este es el hilo 1 Mensaje: este es el hilo 2 Mensaje: este es el hilo 2 Mensaje: este es el hilo 2 Mensaje: este es el hilo 1 Mensaje: este es el hilo 1 Mensaje: este es el hilo 3 Mensaje: este es el hilo 3 Mensaje: este es el hilo 3
El hilo 2 tiene la prioridad más alta y el hilo 3 tiene la prioridad más baja. El primer mensaje lo imprime el hilo de prioridad media 1 porque se inicia poco tiempo antes que el hilo 2.
Contenido relacionado
Tarjeta perforada
CPython
Arquitectura Harvard