next up previous
Siguiente: La API de RT-Linux Arriba: Las tareas de tiempo Previo: Módulos de Linux

   
Ejemplo de tarea de RT-Linux

Para hacernos una idea de cómo programar tareas de tiempo real, veremos a continuación un sencillo ejemplo de registro y activación de una tarea periódica mediante un módulo. Más tarde veremos el resto de las posibilidades que la API (interfaz de programación de aplicaciones) de RT-Linux nos proporciona.

El ejemplo no es más que una tarea que envía una frase al anillo del kernel, cada segundo.

#define MODULE
#include <linux/module.h>
#include <linux/rt_sched.h>

RT_TASK tarea;

void accion(int inutil) {
    static int cont;
    while(1) {
        printk("Activacion numero: %d\n", cont++);
        rt_task_wait();
    }
}

int init_module(void) {
    rt_task_init(&tarea,accion,1,1000,1);
    rt_task_make_periodic(&tarea,
       (RTIME) rt_get_time() + (RTIME) RT_TICKS_PER_SEC,
       (RTIME) RT_TICKS_PER_SEC);
    return(0);
}

int cleanup_module(void) {
    rt_task_delete(&tarea);
    return(0);
}

Para poder compilarla es necesario haber instalado el parche de RT-Linux al núcleo 2.0.33. La orden para compilar sería similar a la que vimos antes.

La tarea es realmente la función accion(). Vemos que es un bucle infinito que hace algo (imprime una frase) y luego ejecuta rt_task_wait(). Esta última función es la que suspende la tarea hasta la próxima activación. De este modo, según lo visto al principio del capítulo, el tiempo de cómputo será el coste de ejecutar la función printk() así como cualquier retraso que suponga la ejecución de la rutina rt_task_wait() hasta lograr la propia suspensión de la tarea. Nótese que la función tiene un parámetro entero que llamamos inutil porque no nos hace falta, pero es obligatorio ponerlo.

Por otro lado, al iniciar el módulo ejecutamos la función rt_task_init() que sirve para registrar la tarea en el planificador (pero no se activa). El primer parámetro de la función es la variable de tipo RT_TASK que permite identificar posteriormente la tarea. El segundo es la propia función a ejecutar. El tercero es el dato de tipo entero que le pasamos como parámetro (en nuestro caso nos daba lo mismo, por lo que le pasamos un 0). El cuarto es el tamaño de la pila local en bytes (recuérdese que la tarea no es un proceso de Linux sino un trozo del código del núcleo, con lo que hay que definir una pequeña zona de pila para variables locales de la tarea, etc). El último es la prioridad de la tarea. La mayor prioridad es 1, y la menor es la definida como RT_LOWEST_PRIORITY. En realidad es un número mayor que 1 ya que se da más prioridad a los procesos con menor valor en este parámetro.

Una vez registrada la tarea, pasamos a decidir cómo se activa. En este caso la vamos a hacer periódica, para lo que se usa la función rt_make_periodic(). El primer parámetro es el identificador de la tarea, el segundo es el instante de la primera activación y el tercero, el período propiamente dicho. Ambos tiempos son del tipo RTIME.

Para calcular el instante de la primera activación, podemos leer el valor actual del reloj y sumarle un retardo, para garantizar que cuando llamemos a esta función el instante elegido sea aun del futuro. Hay que decir que el tiempo en RT-Linux no se especifica en segundos, sino en impulsos de reloj. Para poder hacer conversiones, contamos con la constante RT_TICKS_PER_SEC que nos dice los impulsos emitidos en un segundo.

Así pues podemos programar la tarea para que se active por primera vez a los RT_TICKS_PER_SEC impulsos siguientes al actual (es decir, los impulsos necesarios para hacer un segundo). Y el período lo hacemos igual a RT_TICKS_PER_SEC, es decir, un segundo.

En la función de descarga del módulo es necesario borrar la tarea del planificador, para lo que usamos la función rt_task_delete().

Para acceder a las definiciones mencionadas es necesario incluir en el código el fichero de cabecera linux/rt_sched.h. Para compilar hay que definir la macro __RT__, de modo que la orden de compilación será:

  gcc -O2 -Wall -D__RT__ -D__KERNEL__
    -c ejemplo.c


next up previous
Siguiente: La API de RT-Linux Arriba: Las tareas de tiempo Previo: Módulos de Linux
Juan Jose Amor
1998-07-29