
Examinamos la multitarea, la propiedad del sistema operativo para ejecutar varios programas casi independientes al mismo tiempo. Antes de analizar más de cerca las tareas, debemos ocuparnos de los términos.
Artículos anteriores de la serie:
Artículo # 2. RTOS: estructura y modo en tiempo real
Artículo # 1. RTOS: introducción.
Usamos la palabra "tarea", aunque no tiene un significado exacto. Otros términos, "flujo" y "proceso", son más especializados, y debe comprender lo que significan y en qué se diferencian.
Muchos RTOS utilizados en aplicaciones integradas utilizan un modelo de subprocesos múltiples. Se pueden ejecutar varios hilos simultáneamente, ocupando el mismo espacio de direcciones:

Esto significa que el cambio de contexto es, en primer lugar, cambiar de un conjunto de registros de procesador a otro. Es simple y rápido. El peligro potencial es que cada hilo tenga la capacidad de acceder a la memoria que pertenece a otros hilos o al RTOS mismo.
Una alternativa es el modelo multiproceso. Si se ejecutan varios procesos, cada proceso tiene su propio espacio de direcciones y no puede acceder a la memoria asociada con otros procesos o RTOS:

Esto hace que el cambio de contexto sea más difícil y lento, ya que el sistema operativo debe configurar adecuadamente la unidad de administración de memoria, el administrador de memoria (Unidad de administración de memoria en inglés, MMU). Por supuesto, dicha arquitectura solo es posible con un procesador que admita MMU. Los procesos son compatibles con RTOS de "alto rendimiento" y la mayoría de los sistemas operativos de escritorio. Además, cada proceso puede admitir la división en varios subprocesos, pero esta propiedad rara vez se usa en aplicaciones integradas comunes.
Si hay una MMU disponible, se puede llegar a un compromiso:

Muchos RTOS de "transmisión" admiten MMU para proteger la memoria del acceso no autorizado. Por lo tanto, mientras la tarea está en contexto, solo una parte de su código / datos y las secciones necesarias del RTOS son "visibles"; los bloques de memoria restantes están deshabilitados, y un intento de acceso causará una emergencia (para personas comunes) / excepción (para programadores). Esto hace que el cambio de contexto sea un poco más difícil, pero la aplicación en sí es más segura. Este modo puede denominarse "Modo protegido de subprocesos" o "Modo de proceso ligero".
Planificadores
Como sabemos, la ilusión de la ejecución simultánea de tareas se logra asignando tiempo de procesador para completar cada una de las tareas. Esta es la función central del núcleo. El método de distribuir el tiempo entre tareas se llama "planificación". Programador: software que determina a qué siguiente tarea transferir el control. La lógica del planificador y el mecanismo que determina cuándo y qué debe ejecutarse es el algoritmo de planificación. En esta sección, veremos varios algoritmos de planificación. La planificación de tareas es un tema extenso, y muchos libros están dedicados a ello. Proporcionaremos el mínimo necesario para comprender lo que un RTOS en particular puede ofrecer a este respecto.
Ejecutar al programador de finalización (RTC)
El planificador RTC (ejecución hasta la finalización) es muy simple y consume recursos mínimos. Este es un servicio ideal si cumple con los requisitos de la aplicación. A continuación se muestra un gráfico para un sistema que utiliza el planificador RTC:

El planificador se turna para invocar las funciones de nivel superior de cada tarea. La tarea controla el procesador (lo interrumpe) hasta que la función de nivel superior ejecuta la declaración de retorno return. Si el RTOS admite la suspensión de tareas, las tareas actualmente suspendidas no se ejecutan. Este tema se trata en el siguiente artículo, consulte "Pausa de una tarea".
Una gran ventaja del planificador RTC, además de la simplicidad, es una pila única y la portabilidad del código (no se requiere ensamblaje). La desventaja es que la tarea puede "tomar" el procesador, por lo que se requiere un desarrollo cuidadoso del programa. A pesar del hecho de que cada vez que la tarea se realiza desde el principio (a diferencia de otros programadores que le permiten comenzar a trabajar desde el lugar de detención), puede lograr una mayor flexibilidad con la ayuda de variables de "estado" estáticas que determinan la lógica de cada llamada posterior.
Programador Round Robin (RR)
El planificador RR ("carrusel") es similar a RTC, pero más flexible y, por lo tanto, más complejo:

Sin embargo, en el caso del planificador RR, la tarea no necesita ejecutar la declaración de retorno en la función de nivel superior. Puede liberar el procesador en cualquier momento haciendo una llamada RTOS. Esta llamada hace que el núcleo guarde el contexto de la tarea actual (todos los registros, incluidos el puntero de pila y el puntero de comando) y cargue el contexto de la siguiente tarea en la cola. En algunos RTOS, el procesador puede liberarse (pausar la tarea) antes de la disponibilidad del recurso del núcleo. Esto es más complicado, pero el principio es el mismo.
La flexibilidad del planificador RR está determinada por la capacidad de continuar realizando tareas desde el momento de la suspensión, sin realizar cambios en el código de la aplicación. Para tener flexibilidad, debe pagar menos portabilidad del código y una pila separada para cada tarea.
Time Slice Scheduler (TS)
Scheduler TS (segmento de tiempo - "segmento de tiempo") a un nivel más complejo que RR. El tiempo se divide en intervalos (intervalos, intervalos de tiempo), donde cada tarea se puede realizar dentro de su intervalo asignado:

Además de la capacidad de liberar voluntariamente el procesador, la tarea puede ser interrumpida por una llamada al programador ejecutada por el controlador de interrupción del temporizador del sistema. La idea de asignar un período de tiempo fijo a cada tarea es muy atractiva (cuando sea posible): es fácil de entender y es muy predecible.
La desventaja del planificador TS es que el porcentaje de tiempo de CPU asignado para cada tarea puede diferir, dependiendo de si otras tareas están suspendidas y otras partes de las ranuras están libres:

El planificador de TS puede volverse más predecible si se implementan tareas en segundo plano. La tarea en segundo plano se puede realizar en lugar de cualquier tarea suspendida y ocupar el intervalo de tiempo cuando se libera la tarea (o se detiene).

Obviamente, la tarea en segundo plano no debe realizar un trabajo de tiempo crítico, ya que la parte del tiempo del procesador asignada es absolutamente impredecible: nunca se puede programar.
Dicha solución supone que cada tarea puede predecir cuándo se planificará nuevamente. Por ejemplo, si tiene ranuras para 10 ms y 10 tareas, la tarea sabe que si se libera, continuará ejecutándose después de 100 ms. Con esta solución, puede lograr una configuración más flexible de los ciclos de tiempo (tiempos) para las tareas de la aplicación.
El RTOS puede proporcionar diferentes intervalos de tiempo para cada tarea. Esto proporciona más flexibilidad, pero también es tan predecible como con un tamaño de intervalo fijo. Otra opción es asignar más de un intervalo para la misma tarea, si necesita aumentar la proporción del tiempo de procesador asignado.
Programador prioritario
La mayoría de los RTOS admiten la planificación basada en prioridades. La idea es simple: cada tarea tiene prioridad, y en cualquier momento la tarea que tiene la máxima prioridad y está "lista" para su ejecución se transfiere al procesador:

El programador comienza cuando ocurre un evento (por ejemplo, una interrupción o una llamada a un servicio de kernel específico) que obliga a una tarea con alta prioridad a estar "lista". Hay tres circunstancias bajo las cuales el planificador comienza a funcionar:
• La tarea está suspendida; el planificador debe programar la siguiente tarea.
• Una tarea prepara una tarea de mayor prioridad (mediante una llamada a la API).
• Un controlador de interrupciones (Rutina de servicio de interrupción, ISR) prepara una tarea de mayor prioridad. Esto puede ser un controlador de interrupciones para un dispositivo de E / S o el resultado de un temporizador del sistema.
El número de niveles de prioridad varía (de 8 a varios cientos), los valores de umbral también varían: algunos RTOS perciben la prioridad más alta como 0, mientras que en otros 0 denota la prioridad más baja.
Algunos RTOS permiten solo una tarea en cada nivel de prioridad; otros permiten algunos, lo que complica enormemente las estructuras de datos asociadas. Muchos sistemas operativos le permiten cambiar las prioridades de las tareas en tiempo de ejecución, lo que complica aún más los procesos.
Programador compuesto
Examinamos varios planificadores, sin embargo, muchos RTOS comerciales ofrecen soluciones aún más sofisticadas que tienen las características de varios algoritmos a la vez. Por ejemplo, un RTOS puede soportar múltiples tareas en cada nivel de prioridad, y luego usar TS para dividir el tiempo entre varias tareas preparadas en el nivel más alto.
Estados de la tarea
En un momento dado, solo se realiza una tarea. Además del tiempo de procesador empleado en el controlador de interrupciones (más sobre esto en el siguiente artículo) o el planificador, la tarea "actual" es aquella cuyo código se está ejecutando actualmente y cuyos datos se caracterizan por los valores de registro actuales. Puede haber otras tareas que estén "listas" para el lanzamiento, y el planificador las tendrá en cuenta. En un RTOS simple que usa el planificador RTC, RR o TS, eso es todo. Pero más a menudo, y siempre con un planificador prioritario, las tareas también pueden estar en un estado suspendido, lo que significa que el planificador no las tiene en cuenta hasta que se reanuden y entren en un estado de "preparación".
Pausa una tarea
Pausar una tarea puede ser bastante simple: la tarea se detiene por sí sola (llamando a la API) u otra tarea la detiene. A través de otra llamada API, una tarea suspendida puede ser reanudada por otra tarea o interrumpir el controlador. Esta es una suspensión "incondicional" o "pura". Algunos sistemas operativos llaman a esta tarea "dormir".
El RTOS puede proporcionar a la tarea la capacidad de pausar (quedarse dormido) durante un cierto período de tiempo, después de lo cual se reanuda (según el reloj del sistema). Esto se puede llamar "quedarse dormido".
Si el RTOS admite llamadas API de "bloqueo", se puede utilizar una suspensión más sofisticada. Dicha llamada permite que la tarea solicite un servicio o recurso que recibirá de inmediato si está disponible. De lo contrario, se suspenderá hasta que esté disponible. También se pueden definir tiempos de espera en los que se reanuda la tarea si el recurso no está disponible durante un cierto período de tiempo.
Otros estados de tareas
Muchos RTOS admiten otros estados, pero los conceptos y definiciones varían ampliamente. Por ejemplo, el estado está "terminado", lo que simplemente significa que la función externa de la tarea ha salido (ya sea devolviendo el código o simplemente completando el bloque de funciones externas). Para que la tarea completada comience a ejecutarse nuevamente, es probable que deba restablecerse de alguna manera.
Otra opción es el estado terminado. Esto es similar a una suspensión completa (pura), excepto que la tarea debe restablecerse para reiniciar.
Si el RTOS admite la creación y eliminación dinámicas de tareas (consulte el siguiente artículo), esto implica otro posible estado de la tarea: "eliminado".
Cuando trabajamos en nuestro propio sistema operativo OSRV MAX en tiempo real (artículos publicados anteriormente sobre él), nuestro equipo "encontró" el blog de Colin Walls, un experto en microelectrónica y firmware en Mentor Graphics. Los artículos parecían interesantes, los tradujeron por sí mismos, pero para no "escribir en la mesa" decidieron publicar. Espero que también te sean útiles. Si es así, entonces planeamos publicar todos los artículos traducidos en la serie.
Sobre el autor: Colin Walls ha trabajado en la industria electrónica durante más de treinta años, dedicando la mayor parte de su tiempo al firmware. Ahora es ingeniero de firmware en Mentor Embedded (una división de Mentor Graphics). Colin Walls a menudo habla en conferencias y seminarios, autor de numerosos artículos técnicos y dos libros sobre firmware. Vive en el Reino Unido. Blog profesional de Colin: blogs.mentor.com/colinwalls , correo electrónico: colin_walls@mentor.comLos artículos primero y segundo del ciclo se publican
aquí.