Sistema operativo de tiempo real

De Wikipedia, la enciclopedia libre
Saltar a: navegación, búsqueda

Un sistema operativo de tiempo real es un sistema operativo que ha sido desarrollado para aplicaciones de tiempo real. Como tal, se le exige corrección en sus respuestas bajo ciertas restricciones de tiempo. Si no las respeta, se dirá que el sistema ha fallado. Para garantizar el comportamiento correcto en el tiempo requerido se necesita que el sistema sea predecible.

Características Generales[editar]

Usado típicamente para aplicaciones integradas, normalmente tiene las siguientes características:

  • No utiliza mucha memoria
  • Cualquier evento en el soporte físico puede hacer que se ejecute una tarea
  • Multi-arquitectura (código portado a cualquier tipo de CPU)
  • Muchos tienen tiempos de respuesta predecibles para eventos electrónicos

Se caracterizan por presentar requisitos especiales en cinco áreas generales:

  • Determinismo
  • Sensibilidad
  • Control del usuario
  • Fiabilidad
  • Tolerancia a los fallos

En la actualidad hay un debate sobre qué es tiempo real. Muchos sistemas operativos de tiempo real tienen un programador (en inglés conocido como scheduler), diseños de controladores que minimizan los periodos en los que las interrupciones están deshabilitadas, un tiempo finito conocido (casi siempre calculado para el peor de los casos, término que en inglés se conoce como worst case) de la duración de interrupción. Muchos incluyen también formas especiales de gestión de memoria que limitan la posibilidad de fragmentación de la memoria y aseguran un límite superior mínimo para los tiempos de asignación y retiro de la memoria asignada.

Un ejemplo temprano de sistema operativo en tiempo real a gran escala fue el denominado «programa de control» desarrollado por American Airlines e IBM para el sistema de reservas Sabre.

Procesador[editar]

Este tipo de sistemas operativos no es necesariamente eficiente en el sentido de tener una capacidad de procesamiento alta. El algoritmo de programación especializado, y a veces una tasa de interrupción del reloj alta pueden interferir en la capacidad de procesamiento.

Aunque para propósito general un procesador moderno suele ser más rápido, para programación en tiempo real deben utilizarse procesadores lo más predecibles posible, sin paginación. Todos estos factores en un procesador añade una aleatoriedad que hace que sea difícil demostrar que el sistema es viable, es decir, que cumpla con los plazos de tiempo para la ejecución de las tareas y la atención de los servicios o interrupciones.

Un sistema operativo de tiempo real puede ser implementado en microcontroladores o procesadores digitales de señal "DSP's", así, se pueden desarrollar aplicaciones embebidas en diferentes áreas de la electrónica.

Diseño[editar]

Hay dos diseños básicos:

  • Un sistema operativo guiado por eventos sólo cambia de tarea cuando un evento necesita el servicio.
  • Un diseño la compartición de tiempo cambia de tareas por interrupciones del reloj y por eventos.

El diseño de compartición de tiempo gasta más tiempo de la UCP en cambios de tarea innecesarios. Sin embargo, da una mejor ilusión de multitarea. Normalmente se utiliza un sistema de prioridades fijas.

Uno de los algoritmos que suelen usarse para la asignación de prioridades es el Rate-Monotonic Schedule. Si el conjunto de tareas que tenemos es viable con alguna asignación de prioridades fijas, también es viable con el Rate-Monotonic Schedule, donde la tarea más prioritaria es la de menor periodo. Esto no quiere decir que si no es viable con Rate-Monotonic Schedule no sea viable con asignaciones de prioridad variable. Puede darse el caso de encontrarnos con un sistema viable con prioridades variables y que no sea viable con prioridades fijas.

Programación[editar]

En los diseños típicos, una tarea tiene tres estados: ejecución, preparada y bloqueada. La mayoría de las tareas están bloqueadas casi todo el tiempo. Solamente se ejecuta una tarea por UCP. La lista de tareas preparadas suele ser corta, de dos o tres tareas como mucho.

El problema principal es diseñar el programador. Usualmente, la estructura de los datos de la lista de tareas preparadas en el programador está diseñada para que cada búsqueda, inserción y eliminación necesiten interrupciones de cierre solamente durante un período muy pequeño, cuando se buscan partes de la lista muy definidas.

Esto significa que otras tareas pueden operar en la lista asincrónicamente, mientras que se busca. Una buena programación típica es una lista conectada bidireccional de tareas preparadas, ordenadas por orden de prioridad. Hay que tener en cuenta que no es rápido de buscar sino determinista. La mayoría de las listas de tareas preparadas sólo tienen dos o tres entradas, por lo que una búsqueda secuencial es usualmente la más rápida, porque requiere muy poco tiempo de instalación.

El tiempo de respuesta crítico es el tiempo que necesita para poner en la cola una nueva tarea preparada y restaurar el estado de la tarea de más alta prioridad.

En un sistema operativo en tiempo real bien diseñado, preparar una nueva tarea necesita de 3 a 20 instrucciones por cada entrada en la cola y la restauración de la tarea preparada de máxima prioridad de 5 a 30 instrucciones. En un procesador 68000 20MHz, los tiempos de cambio de tarea son de 20 microsegundos con dos tareas preparadas.

Cientos de UCP MIP ARM pueden cambiar en unos pocos microsegundos.

Comunicación entre Tareas[editar]

Las diferentes tareas de un sistema no pueden utilizar los mismos datos o componentes físicos al mismo tiempo. Hay dos métodos para tratar este problema.

Uno de los métodos utiliza semáforos. En general, el semáforo binario puede estar cerrado o abierto. Cuando está cerrado hay una cola de tareas esperando la apertura del semáforo.

Los problemas con los diseños de semáforos son bien conocidos: inversión de prioridades y puntos muertos (deadlocks).

En la inversión de prioridades, una tarea de mucha prioridad espera porque otra tarea de baja prioridad tiene un semáforo. Si una tarea de prioridad intermedia impide la ejecución de la tarea de menor prioridad, la de más alta prioridad nunca llega a ejecutarse. Una solución típica sería otorgar a la tarea que tiene el semáforo la prioridad de la tarea más prioritaria de las que están esperando dicho semáforo. Esto se denomina algoritmo de herencia básica de prioridad.

En un punto muerto, dos tareas (T1,T2) pretenden adquirir dos semáforos (semA, semB) en orden inverso. En este caso si T1 adquiere semA y T2 adquiere semB cuando intenten adquirir el segundo semáforo no podrán hacerlo ya que lo tiene la otra tarea. De esta forma entran en un punto muerto del que ninguna de las dos tareas puede salir sin intervención externa. Esto se resuelve normalmente mediante un diseño por ej. obligando a adquirir los semáforos en un orden concreto.

La otra solución es que las tareas se manden mensajes entre ellas. Esto tiene los mismos problemas: La inversión de prioridades tiene lugar cuando una tarea está tratando un mensaje de baja prioridad, e ignora un mensaje de más alta prioridad en su correo. Los puntos muertos ocurren cuando dos tareas realizan envíos bloqueantes (se quedan en la función de envío esperando a que el receptor reciba el mensaje). Si T1 manda un mensaje de forma bloqueante a T2 y T2 manda un mensaje de igual forma a T1 ninguna de las dos tareas saldrá de la función de envío quedando ambas bloqueadas ya que no podrán llegar a la función de recepción. Puede resolverse reordenando envíos y recepciones o empleando envíos no bloqueantes o temporizados.

Aunque su comportamiento en tiempo real es algo más difícil de analizar que los sistemas de semáforos, los sistemas basados en mensajes normalmente son más sencillos de desarrollar que los sistemas de semáforo.

Interrupciones[editar]

Las interrupciones son la forma más común de pasar información desde el mundo exterior al programa y son, por naturaleza, impredecibles. En un sistema de tiempo real estas interrupciones pueden informar diferentes eventos como la presencia de nueva información en un puerto de comunicaciones, de una nueva muestra de audio en un equipo de sonido o de un nuevo cuadro de imagen en una videograbadora digital.

Para que el programa cumpla con su cometido de ser tiempo real es necesario que el sistema atienda la interrupción y procese la información obtenida antes de que se presente la siguiente interrupción. Como el microprocesador normalmente solo puede atender una interrupción a la vez, es necesario que los controladores de tiempo real se ejecuten en el menor tiempo posible. Esto se logra no procesando la señal dentro de la interrupción, sino enviando un mensaje a una tarea o solucionando un semáforo que está siendo esperado por una tarea. El programador se encarga de activar la tarea y esta se encarga de adquirir la información y completar el procesamiento de la misma.

El tiempo que transcurre entre la generación de la interrupción y el momento en el cual esta es atendida se llama latencia de interrupción. El inverso de esta latencia es una frecuencia llamada frecuencia de saturación, si las señales que están siendo procesadas tienen una frecuencia mayor a la de saturación, el sistema será físicamente incapaz de procesarlas. En todo caso la mayor frecuencia que puede procesarse es mucho menor que la frecuencia de saturación y depende de las operaciones que deban realizarse sobre la información recibida.

Memoria[editar]

Hay dos problemas con el reparto de la memoria en SOTR (sistemas operativos en tiempo real).

El primero, la velocidad del reparto es importante. Un esquema de reparto de memoria estándar recorre una lista conectada de longitud indeterminada para encontrar un bloque de memoria libre; sin embargo, esto no es aceptable ya que el reparto de la memoria debe ocurrir en un tiempo fijo en el SOTR.

En segundo lugar, la memoria puede fragmentarse cuando las regiones libres se pueden separar por regiones que están en uso. Esto puede provocar que se pare un programa, sin posibilidad de obtener memoria, aunque en teoría exista suficiente memoria. Una solución es tener una lista vinculada LIFO de bloques de memoria de tamaño fijo. Esto funciona asombrosamente bien en un sistema simple.

La paginación suele desactivarse en los sistemas en tiempo real, ya que es un factor bastante aleatorio e impredecible, que varía el tiempo de respuesta y no nos permite asegurar que se cumplirán los plazos, debido al trasiego de páginas de memoria con un dispositivo de almacenamiento (thrashing)

Comunicaciones[editar]

Para las comunicaciones se suelen usar conexiones o redes deterministas CAN bus o puertos serie, ya que las redes más usuales, como Ethernet son indeterministas y no pueden garantizarnos el tiempo de respuesta. El sistema CAN bus es utilizado para la interconexión de dispositivos electrónicos de control (ECU) en los vehículos.

Algunos Ejemplos[editar]

Enlaces externos[editar]