Introducción a los sistemas multitarea

Los sistemas multitarea

La multitarea es una característica ofrecida por los sistemas operativos modernos que permite la ejecución de múltiples procesos o tareas independientes de forma alternativa sobre la misma CPU dando la apariencia de que se ejecutan al mismo tiempo.

Casi todos los sistemas operativos de hoy en día son sistemas multitarea. Ejemplo de ello lo encontramos en sistemas de uso genérico como Linux, Windows, Android, IOS, etc., en los cuales podemos estar escuchando Spotify a la vez que consultamos el Facebook, jugamos a un videojuego y escribimos en un Word nuestro trabajo de fin de grado. 
 
The Illusion of Multitasking Boosts Performance – Association for  Psychological Science – APS

Sin embargo la multitarea no es exclusiva únicamente de los computadores de uso genérico. La mayoría de sistemas embebidos también implementan este tipo de computación, que les aporta unas capacidades enormes.

 

El origen. La programación secuencial.

Los sistemas embebidos más básicos suelen estar diseñados de tal modo que poseen un bucle infinito, a veces denominado "superloop", que ejecuta secuencialmente (en orden) las diferentes funciones del programa. 

Esta es la estructura de programación más básica, la cual todos los programadores de sistemas embebidos aprenden al comienzo de su carrera.

	                
               void main(){
                    while(1)						//infinite loop
                    {
                        digitalWrite(LED,HIGH);
                        delay(1000);
                        digitalWrite(LED,LOW);
                        delay(1000);
                    }
                }
    

Esta estructura suele ejecutarse directamente sobre la CPU, sin ningún sistema operativo subyacente, en lo que se conoce como "bare-metal programming". Así, todos los recursos de la CPU están destinados a esa única "superfunción".

La característica principal de este enfoque es que cada parte del código se ejecuta únicamente cuando se cumple una condición determinada. En el ejemplo anterior, el led no se apagará o encenderá hasta que se haya cumplido una condición temporal (time delay).

 

Inconvenientes de la programación secuencial.

Como vimos anteriormente, la programación secuencial ejecuta las diferentes partes de código en orden. Esto presenta una clara limitación a la hora de proyectar sistemas cuya ejecución no siga una línea perfectamente determinada e invariable. Sucesos aleatorios (muy comunes en el mundo real) ante los cuales el sistema debiera reaccionar son prácticamente imposibles de afrontar con este tipo de programación.

Esta estructura que "para" o bloquea su ejecución mientras espera a un determinado evento, no puede atender a ninguna otro suceso o realizar otras tareas a la vez. 

El resultado es un sistema inmutable, acoplado y desestructurado en el cual la complejidad del mismo se multiplicará con cada elemento que añadamos hasta el punto en el cual el desarrollo del mismo se vuelva una tarea abocada al fracaso. 

Ejemplo: Con la estructura anterior somos capaces de hacer un programa muy sencillo que desarrolle cíclicamente los siguientes pasos:

1. Lectura de un sensor.

2. Ajuste de la velocidad del un motor de acuerdo al valor del sensor.

3. Registro de la lectura del sensor en un fichero. 

¿Qué pasaría por ejemplo si los datos del sensor se retrasasen? ¿Y si lo hiciese el envío de los datos al fichero? 

Con esta estructura rápidamente percibiríamos una reducción de la funcionalidad de nuestro sistema. E
n el caso (bastante probable) de que la acción de guardar datos en el fichero tardase más de la cuenta, la lectura del sensor se retrasaría, al igual que la modificación de la velocidad del motor. Obtendríamos pues un sistema poco repetible y robusto apto para muy pocas aplicaciones reales.

En este ejemplo se ha tomado una secuencia de tan solo tres acciones. ¿Imaginas un sistema encargado de controlar todo el complejo sistema de un motor a reacción de un avión comercial?

La pregunta que surge después de esto es: ¿Cómo hacen entonces los sistemas embebidos actuales para estar pendientes del control de uno o decenas de motores a la vez que toman datos de uno o decenas de sensores, envían datos a través de Internet, hacen sonar una alarma, iluminan una pantalla e infinitas cosas más todo al mismo tiempo? 

La respuesta la encontramos en el multitasking o la multitarea.


Dando paso a los sistemas multitarea.

Como hemos visto, la programación con un solo bucle o tarea no permite a nuestro sistema más que un solo hilo de ejecución. Una solución lógica es pensar que varios bucles podría solucionar el problema. En efecto, esto es en lo que se basan los sistemas multitarea, en la utilización de múltiples hilos de ejecución (tareas) independientes.

El multitasking o la multitarea es una característica que ofrecen los sistemas operativos modernos y que permite la creación y ejecución de múltiples tareas (superloops) sobre la misma CPU, logrando desacoplar cada hilo de ejecución. Así, el sistema operativo intercambiará de una tarea a otra (context switching) cuando se requiera.

TaskExecution.gif 

Con este nuevo enfoque, cada una de las tareas que nuestro sistema debe afrontar (leer un sensor, mover un motor, guardar datos en un fichero...) se pueden separar en tareas individuales que se ejecutaran alternativamente.

Ejemplo: Si atendemos a la pregunta de la sección anterior veremos que un sistema embebido moderno no está controlando motores, tomando datos de los sensores, iluminando pantallas, haciendo sonar alarmas y enviando datos por Internet todo al mismo tiempo. En realidad, solo un proceso se lleva a cabo a la vez. Lo que realmente ocurre es que los procesos se alternan en la CPU de tal modo que unas tareas se ejecutan cuando otras no tienen nada que hacer.

Siendo la CPU tan rápida en comparación con el ser humano, el efecto producido es que parece que se estén ejecutando todas al mismo tiempo. 

 

Beneficios e inconvenientes de los sistemas multitarea

Los sistemas multitarea otorgan beneficios fundamentales para el correcto desarrollo de sistemas complejos, algunas de ellos son:

  1. Divide y vencerás: Múltiples tareas son más fáciles de desarrollar e implementar que una sola macro-tarea. 

  2. Uso más eficiente de la CPU. Una CPU bloqueada ("dormida") consume ciclos de cómputo que podrían ser usados para ejecutar otras tareas. Los sistemas multitarea minimizan los ciclos en los que la CPU está bloqueada.

  3. Tareas desacopladas en el dominio temporal. La ejecución de código está desacoplada, permitiendo saltos de una parte a otras del mismo. Además  algunos schedulers, más concretamente los preemptivos, basados en prioridad, permiten asegurar que las tareas con más prioridad se ejecuten antes que las de menor prioridad.  

 

Por contra, al trabajar con sistemas multitarea, diferentes recursos del sistema tanto software (variables, funciones, capas de abstracción, etc.) como hardware (periféricos, timers, CPU, memoria, etc.) son compartidos por las distintas tareas dando lugar a cuestiones avanzadas de sincronización y comunicación entre las mismas.

El programador que trabaje con sistemas multitarea, también llamados sistemas concurrentes, deberá disponer de amplios conocimientos sobre la función y uso de los sistemas operativos así como las técnicas que se utilizan para solventar los problemas anteriormente citados. Entre ellos nombramos los semáforos, señales, colas de mensajes, memoria compartida, sockets, etc.


Los sistemas de tiempo real en los sistemas embebidos. 

Existen multitud de sistemas operativos, cada uno de ellos con funcionalidades destinadas a aplicaciones particulares. Dentro de las diferencias que pueden presentar cada uno de ellos, una de las más importantes en cuanto a sistemas embebidos se refiere, es, precisamente, la forma en que las diferentes tareas se intercambian entre ellas y ejecutan en la CPU.

Debido a las duras restricciones temporales a las que se ven sometidos las tareas de la mayoría de los sistemas embebidos estos incorporan sistema que les permita controla exactamente el momento en el que cada una de las tareas se ejecuta. Estos sistemas operativos multitarea, son conocidos con el nombre de Sistemas Operativos de Tiempo Real (RTOS).

Ejemplo: Un marcapasos es un sistema embebido critico del cual depende la vida de un ser humano. En estos dispositivos la ejecución de las diferentes tareas en el tiempo exacto es determinante. Para provocar la contracción del corazón, el pulso eléctrico suministrado tiene que darse en el momento preciso, de lo contrario puede provocar molestias en el paciente, provocar arritmias e incluso colapsar el corazón.


La funcionalidad de los sistemas operativos en tiempo real está directamente relacionada con el planificador o "scheduler" del sistema operativo multitarea. El scheduler es el algoritmo encargado de planificar cuál va a ser la siguiente tarea en ganar el acceso a la CPU y ejecutarse. Dependiendo del tipo de scheduler que tenga nuestro sistema operativo, tendremos unas capacidades u otras.

Los sistemas operativos en tiempo real, de los cuales hablaremos más adelante, incorporan, por lo general un scheduler de tipo preemptivo basado en prioridades el cual permite que las tareas se ejecuten en el tiempo preciso en el que deben, siguiendo, además, un esquema de prioridades. Así, en caso de que dos tareas coincidan en su momento de ejecución, aquella con mayor prioridad, es decir, la más critica para el correcto funcionamiento del sistema, se ejecutara primer, posponiendo la de menos prioridad para más tarde.









 

 

Comments

Popular posts from this blog

¿Qué es un sistema embebido?

Patrones software en arquitecturas orientadas a control