8 RTLinux
8 RTLinux
8 RTLinux
VxWorks
• De Wind River, que es subsidiaria de Intel desde julio de 2009
• Con soporte para multiprocesadores, IPv6 y un sistema de archivos
• Con protección de memoria: O sea que las tareas no pueden alterar
la memoria de trabajo de otras tareas
• Funciona en las plataformas de embebidos más populares
• Se usa con un IDE para Windows/Linux, que normalmente incluye
depurador, simulador y herramientas de análisis
QNX
• De QNX, subsidiaria de Research in Motion (los del Blackberry)
desde mayo de 2010
• Símil Unix, ofrece funcionalidad parecida al VxWorks
• En 2007 fue abierto el código de su núcleo
RTLinux
• Basado en Linux
FreeRTOS
• Es gratuito
KURT
Características de los SOTR
• Deshabilitación de interrupciones
El núcleo dehabilita las interrupciones para
implementar las exclusion mutua (secciones críticas).
Si Linux dehabilita las interrupciones y hay una
interrupción de reloj, esto realiza su bloqueo y
consecuentemente hay una perdida de precisión
temporal, poniendo en peligro la respuesta oportuna
frente a eventos externos (produciendo que el tiempo
de ejecución sea impredecible).
RTL implementa una solución elegante: las llamadas
a CLI, STI y IRET son reemplazadas por S_CLI,
S_STI y S_IRET que las emulan, así Linux nunca las
dehabilita.
Soluciones a los problemas de los S.O. Convencionales
• Micronúcleo (Microkernel):
La parte del sistema operativo en Tiempo Real,
denominada micronúcleo, ofrece un conjunto básico de
servicios para los demás procesos:
Creación de procesos e hilos adicionales.
Mensajes entre hilos.
Sincronización
Temporizadores en tiempo real
netscape
bash staroffice
System Call
SO Linux
driver
Interrupción I/O
Hardware
Arquitectura de RTLinux
Hardware
Módulos en RTLinux
Módulos cargables
rtl_sched.o planificador de prioridad
rtl_time.o controla los clocks del procesador
rtl_posixio.o soporte interface a drivers al estilo
posix: read, write, open
rtl_fifo.o conecta tareas RT y handlers de
interrupción a procesos linux
rtl_mutex.o para sincronización de recursos
El Planificador
Creación/destrucción Cancelación
• pthread_create • pthread_cancel
• pthread_exit • pthread_setcancelstate
Atributos • pthread_setcanceltype
• pthread_attr_init • pthread_testcancel
• pthread_attr_destroy • pthread_delete_np
• pthread_attr_setschedparam Threads periódicos (no estándar)
• pthread_attr_getschedparam • pthread_make_periodic_np
• sched_get_priority_max • pthread_setperiod_np
• sched_get_priority_min • pthread_wait_np
• pthread_attr_setstacksize Atributos (no estándar)
Control de ejecución (no estándar) • pthread_attr_setfp_np
• pthread_suspend_np • pthread_attr_setfp_np
• pthread_wakeup_np • pthread_attr_setcpu_np
• pthread_attr_getcpu_np
Creación y destrucción de Hilos
• pthread_exit(retval)
Termina la ejecución del thread que invoca esta llamada,
retornando como valor de terminación retval.
• pthread_join(thread, retval)
Suspende la ejecución del thread que invoca esta llamada hasta
que thread termina su ejecución. En la implementación actual
todos los threads son creados PTHREAD_CREATE_JOINABLE
sin posibilidad de ser modificado.
Atributos
• pthread_attr_init(*attr), pthread_attr_init_destroy(*attr)
Los atributos de creación de tareas se pasan en una estructura
de tipo pthread_attr_t. El acceso a los campos de esta estructura
se realiza mediante funciones simulando la POO.
• pthread_attr_[get|set]schedparam(*attr, *sched_param)
Establece la prioridad de la nueva rtl-task. Por ahora (V3) sólo
está disponible la política SCHED_FIFO. El rango de prioridades
válido se obtiene de funciones sched_get_priority_min y
sched_get_priority_max. (0, 100000)
• pthread_attr_[set|get]fp_np(*attr, flag)
Para reducir el tiempo de cambio de contexto por defecto
RTLinux no salva a memoria el estado de coprocesador
matemático. Si queremos que las rtl-tasks puedan utilizar el
coprocesador entonces es necesario llamar a esta función.
Atributos
• pthread_attr_[set|get]cpu_np(*attr, cpu)
Asigna el nuevo thread que se crea con attr al procesador cpu
(sistema SMP). La numeración de los procesadores esta en el
fichero /proc/cpuinfo.
• pthread_attr_setstacksize(*attr, size)
Todos los threads comparten el mismo espacio de memoria, pero
cada uno ha de tener su propia pila.
Hilos periódicos, NO portables
•pthread_setperiod_np(thread, *itime)
Equivalente a la función anterior pero utilizando una estructura
del tipo timerspec para especificar el instante de inicio y el
periodo.
•pthread_wait_np()
Suspende la ejecución del thread que la invoca. Es necesario
que el thread tenga un funcionamiento periódico.
Cancelación
•pthread_cancel(thread)
La cancelación es el mecanismo por el cual un thread invoca la terminación
de otro.El thread puede terminar o no en función de su estado de
"cancelación".
•pthread_setcanceltype(type, *oldtype)
Establece el tipo de cancelación. Estos dos tipos se denominan
respectivamente: PTHREAD_CANCEL_ASYNCHRONOUS, y
PTHREAD_CANCEL_DEFERRED. El primero se realiza inmediatamente
cuando otro thread llame a la función pthread_cancel. El otro, solo se puede
en ciertos punto de la ejecución del thread debido a que se pueda dejar el
sistema en un estado estable antes de finalizar (liberar semáforos, cerrar,
ficheros, etc.). Opción por defecto.
•pthread_testcancel()
Comprueba si hay pendiente alguna petición de cancelación y si es así
termina el thread que la invoca. Sólo tiene sentido si el thread está en estado
PTHREAD_CANCEL_ENABLE y tipo PTHREAD_CANCEL_DEFERRED.
Control de Ejecución
• pthread_suspend_np(thread)
Envía la señal RTL_SIGNAL_SUSPEND a un thread,
suspendiendo la ejecución del mismo. Para volver a activarlo
hay que enviarle la señal RTL_SIGNAL_WAKEUP o llamar a
pthread_wakeup_np.
• pthread_wakeup_np(thread)
Envía la señal RTL_SIGNAL_WAKEUP a un thread, reanudando
su ejecución.
Ejemplo 1: Tarea RT periódica
#include <rtl.h>
#include <time.h>
#include <pthread.h>
pthread_t thread;
/*tarea RT periodica */
void * thread_code(void)
{
pthread_make_periodic_np(pthread_self(), gethrtime(),
1000000000);
while (1) {
pthread_wait_np ();
rtl_printf("Hello World\n");
}
return 0;
}
int init_module(void) {
return pthread_create(&thread, NULL, thread_code, NULL);
}
void cleanup_module(void) {
pthread_delete_np(thread);
}
Ejemplo 2: Tarea RT periódica
#include <rtl.h>
#include <time.h>
#include <pthread.h>
pthread_t tareaRTperiodica;
/*tarea RT periodica */
void * rutina(void *arg)
{ struct sched_param p;
int nperiodos=0;
p.sched_priority=1;
pthread_setschedparam (pthread_self(),SCHED_FIFO, &p);
pthread_make_periodic_np(pthread_self(),gethrtime(),500000000);
/* periodo 0.5 seg */
while(1)
{ pthread_wait_np ();
rtl_printf("Periodo %d\n",nperiodos); nperiodos++;
}
return 0;
}
Ejemplo 2: Tarea RT periódica
Nota:
• Si la tarea rutina() tarda mucho, LINUX “se colgará”.
• Comprobar como afectan las tareas RT a procesos Linux: Variar periodo
o tiempo de computo y ejecutar algún proceso Linux al mismo tiempo.
¿Está más pesado el sistema?. Si el procesador está un poco más
pesado, recuerde que Linux corre más lento que lo usual.
NOTAS
• Listado de señales
• RTL_SIGNAL_NULL, no causa ninguna acción sobre el thread
destino.
• RTL_SIGNAL_SUSPEND, suspende la ejecución del hilo que recibe
esta señal.
• RTL_SIGNAL_WAKEUP, despierta el thread.
• RTL_SIGNAL_CANCEL, es equivalente a usar la función
pthread_cancel(hilo)
• RTL_LINUX_MIN_SIGNAL, equivale a enviar una interrupción
software al núcleo de Linux.Esta señal representa la interrupción 0.
• RTL_SIGNAL_KILL, termina la ejecución.
Esquema global de la gestión de
interrupciones
Habilitar/inhabilitar
interrupciones
Interrupciones
Interrupciones hardware
software
Enmascarar
interrupciones
Gestión de
Tiempo
Gestión de Tiempo
• Operaciones
Gestión de los relojes
Gestión de temporizadores:
Relativos o absolutos
Un solo disparo o periódicos
Retardo de alta resolución
Listado de Funciones
Leer el tiempo
• clock_gettime () Control
• clock_gethrtime () • rtl_getschedclock ()
• gethrtime () • rtl_setclockmode ()
• rtl_getbestclock ()
Temporización: Retardos
• rtl_delay ()
• nanosleep ()
• clock_nanosleep ()
Tipo de Datos que emplean las funciones
struct timespec {
time_t tv_sec;
Long tv_nsec;
};
• hrtime_t gethrtime()
Devuelve el tiempo actual en nanosegundos del reloj más
eficiente.
• hrttime_t gethrtimeres()
Devuelve la resolución del tiempo que devuelve gethrtime().
• hrttime_t clock_gethrtime( clockid_t clock)
Devuelve el tiempo actual del reloj indicado. El reloj puede ser
alguno de los tres relojes lógicos o dos físicos disponibles en
RTLinux:
CLOCK_REALTIME
CLOCK_MONOTONIC
CLOCK_RTL_SCHED
CLOCK_8254
CLOCK_APIC
Funciones de Temporización, esperas
• rtl_delay(long duracion)
Realiza una espera activa de duración en nanosegundos.
Se puede utilizar desde una tarea RT o un manejador de
interrupción.
• usleep(unsigned duracion)
Realiza una espera NO activa de duración en microsegundos.
La espera se realiza suspendiendo el thread, por lo que no se
puede llamar desde un manejador de interrupción.
• nanosleep(struct timespec *espera,struct timespec *restante);
Realiza un espera NO activa de duración en nanosegundos. En
restante se devuelve el tiempo que queda de la espera en caso
de que se abortará por recibir alguna señal.
Funciones de Control
• rtl_getschedclock()
Retorna el identificador usado por el planificador
• rtl_getbestclock()
Retorna el identificador del reloj mas eficiente disponible
• rtl_setclockmode()
Establece el modo de operación del reloj especificado ( un
disparo periódico)
Sincronización
Sincronización
Semáforos
pthread_mutex_init Variables condición
pthread_mutex_destroy pthread_cond_init
pthread_mutex_lock pthread_cond_destroy
pthread_mutex_trylock pthread_cond_wait
pthread_mutex_unlock pthread_cond_broadcast
Atributos de semáforos pthread_cond_signal
pthread_mutexattr_init pthread_cond_timedwait
pthread_mutexattr_settype Atributos variable condicion
pthread_mutexattr_destroy pthread_condattr_init
pthread_mutexattr_setpshared
pthread_condattr_destroy
pthread_mutexattr_getpshared
pthread_condattr_getpshared
pthread_mutexattr_settype
pthread_condattr_setpshared
pthread_mutexattr_gettype
pthread_mutexattr_setprotocol Herencia dinámica
pthread_mutexattr_getprotocol pthread_mutex_setprioceiling
pthread_mutexattr_setprioceiling pthread_mutex_getprioceiling
pthread_mutexattr_getprioceiling
Paralelismo
y
Concurrencia
Paralelismo y concurrencia
#include <rtl.h>
#include <time.h>
#include <pthread.h>
#include <rtl_core.h>
#include <rtl_sched.h>
#include <errno.h>
pthread_t thread1,thread2;
int init_module(void)
{
pthread_attr_t attr;
struct sched_param sched_param;
int thread_status;
rtl_printf("El modulo de arranque esta en la CPU %d\n",rtl_getcpuid());
pthread_attr_init(&attr);
pthread_attr_setcpu_np(&attr, 0);
sched_param.sched_priority = 1;
pthread_attr_setschedparam(&attr,&sched_param);
pthread_create(&thread1,&attr,start_routine,"Hello ");
pthread_attr_setcpu_np(&attr, 1);
pthread_create(&thread2,&attr,start_routine,"World!");
return 0;
}
Mecanismo de comunicación
entre tareas : FIFO
FIFO
SO Linux
Floppy FIFO
FIFO
/dev/rtf1
cat cat
/dev/rtf0
/dev/fd0
SO Linux
Floppy FIFO
Desde el punto de vista de un
Proceso Linux normal
#include <fcntl.h>
main () {
int fd, count;
int valor;;
fd=open("/dev/rtf0", O_RDONLY);
while (1) {
read(fd, sizeof(valor));
printf("valor: %8d\n", valor);
}
}
Desde el punto de vista de una
Tarea de tiempo real
• rtf_create_handler(fifo_nr, function)
Instala una función manejadora que se invoca cada vez
que un proceso normal de Linux lee o escribe sobre la fifo
indicada. Sólo se llama la función cuando se ha llevado a
cabo la operación con éxito, p.e. una operación de lectura
sobre una fifo vacía no causa la llamada del manejador
hasta que se escribe y luego se completa la llamada de
lectura. Para desinstalar un manejador nuestro tenemos
que instalar la función manejadora por defecto
(default_handler):
rtf_create_handler(n_fifo,default_handler).
•rtf_create_rt_handler(fifo_nr, function)
Instala una función manejadora que se invoca cada vez
que alguna tarea de tiempo real lee o escribe sobre la fifo
indicada. El manejador se desinstala de igual forma que el
manejador anterior.
Uso de FIFOS desde RTLINUX