Linux Real-Time
Introduzione a
POSIX1003.1b
E.Mumolo, DEEI
[email protected]
Il Sistema Operativo Linux

Numerazione versioni di linux: a.b.c (es. 2.4.16) dove




a  no. versione,
b  kernel stabile (se pari), in sviluppo (se dispari)
c  no. di rilascio del kernel (se pari stabile, se dispari in sviluppo)
Storia del kernel
Linux non è in tempo reale


Linux è nato come un sistema multiutente per usi generali

Sistemi Operativi per usi generali massimizzano il throughput alle spese
del tempo d'attesa

Sistemi Operativi in tempo reale minimizzano il tempo d'attesa alle
spese del throughput
In particolare:




Le chiamate di sistema di Linux non sono interrompibili → tempi d'attesa
non riducibili
Linux usa memoria paginata → tempi d'attesa impredicibili
Linux usa una schedulazione equa → trattando in modo equanime tutti i
processi si penalizzano i processi a alta priorità
Linux ordina le richieste di I/O per ottimizzare l'uso dell'I/O → un
processo a bassa priorità potrebbe avere precedenza rispetto ad uno a
alta priorità
Prestazioni di Linux
Sistemi in tempo reale


Un sistema opera in tempo reale soltanto se fornisce i
risultati attesi entro predefiniti limiti temporali
Proprietà desiderate:
 non solo






ma anche



correttezza
affidabilità
flessibilità
portabilità
riusabilità
efficienza
prevedibilità
Attenzione: Tempo reale non significa necessariamente
elevata potenza di calcolo!
Tipi di processo

Real-time con vincoli temporali



Hard rt se la relativa deadline deve sempre essere
rispettata
 Periodico con frequenza di esecuzione costante
 Sporadico in caso contrario
Soft se la relativa deadline può essere disattesa in
condizioni di temporaneo sovraccarico
 Periodico con frequenza di esecuzione costante
 Aperiodico in caso contrario
Non real-time senza vincoli temporali
Tipologie di schedulazione


Off-line
 se integralmente pianificata a priori
On-line
 se stabilita a tempo di esecuzione in base a parametri
attribuiti ai processi in maniera






statica
dinamica
Guaranteed
 se rispetta i vincoli di esecuzione di ogni processo
Best-effort
 se tende viceversa ad ottimizzare le prestazioni medie
dell’insieme di processi
Preemptive
 se l’esecuzione di un processo può essere sospesa
Non-preemptive in caso contrario
Sistemi embedded e sistemi in tempo reale

I sistemi ‘embedded’ (dedicati) sono quelli che fanno parte
integrante di un dispositivo



Ad esempio: un calcolatore PDA, un telefono cellulare, una
segreteria telefonica elettronica, una centralina di controllo di
un’automobile sono tutti sistemi che vengono attivati
all’accensione del dispositivo di cui fanno parte integrale
A seconda dei vincoli temporali richiesti dal dispositivo i sistemi
possono essere considerati in tempo reale o meno
Una delle caratteristiche più importanti del sistema in tempo
reale è il tempo con cui il sistema risponde a eventi interni
(segnali o trappole software) o esterni (timer esterni o
interrupt hardware).
Sistemi embedded e sistemi in tempo reale

Una prima misura della risposta del sistema è la latenza, cioè
il tempo che intercorre tra l’evento e la prima istruzione della
routine di servizio dell’evento

Una seconda misura è lo jitter, la variazione del periodo di
eventi periodici con periodo costante

Per essere in grado di presentare bassa latenza e basso jitter,
il sistema operativo deve garantire che il kernel venga
interrotto da i processi in tempo reale.
Alcuni SO in tempo reale

VxWorks (Motorola, Pentium, StrongArm, Arm)




Windows CE .NET (ARM, StrongArm, XScale, MIPS, Pentium)







Microkernel, aderisce a POSIX
Prestazioni su Pentium 200: latenza media 1.6 us, latenza massima 4.1 us
pSOSystem 3


Non aderisce a POSIX
Prestazioni su Pentium 200: latenza media 2.4 us, latenza massima 5.6 us
QNX Neutrino RTOS (Pentium, Power PC, ARM, StrongArm, XScale,
MIPS, SH-4)


Aderisce a POSIX
Robotica, controllo di processi, avionica, telecomunicazioni, medicina
Prestazioni su Pentium 200: latenza media 1.7 us, latenza massima 6.8 us
Aderisce a POSIX
Prestazioni su Pentium 200: latenza media 1.9 us, latenza massima 3.8 us
Arx RTOS http://arx.snu.ac.kr/html/overview-arx.en.html
AvSys http://www.avocetsystems.com
CMX RTOS http://www.cmx.com
Progetti Linux Real Time

Primo approccio: eliminazione di funzionalità dal kernel Linux
standard.



Secondo approccio: modifiche al kernel Linux standard.




Ridurre la complessità e la dimensione del sistema operativo, con
particolare attenzione alle sezioni con comportamenti meno
deterministici;
Es.: uCLinux http://www.uclinux.org
Sostituire lo scheduler standard Linux con un algoritmo più
deterministico
Aggiungere punti di chiamata dello scheduler in punti “sicuri” dei
sorgenti del kernel, per renderlo più reattivo.
Es.: Montavista's Hard Hat Linux, KURT;
http://www.mvista.com/products/hhl.html;http://www.ittc.ku.edu/kurt/
Terzo approccio: Linux all’interno di un sistema real-time


Eseguire Linux come processo a bassa priorità di un minimo kernel
real-time. Questo kernel gestisce l’hardware direttamente, offrendo a
Linux una simulazione software (macchina virtuale).
Es.: RTLinux, RTAI; http://www.rtlinux.org/; http://www.rtai.org/
In sintesi: Soluzioni Real Time più popolari

Alcuni dei sistemi operativi realtime “generici”:


Soluzioni proprietarie:

VxWorks

QNX

RTLinuxPro
Soluzioni opensource:

RTLinuxFree (solo per kernel 2.4)

RTAI

RTLinux e RTAI sono soluzioni basate sul kernel di
Linux

Possono sfruttare tutte le applicazioni e l'ambiente
del sistema operativo di partenza.
Architettura di RTAI

Sviluppato dal Dipartimento di Ing.Aereospaziale, Università di Milano,
www.rtai.org

Si introduce un nuovo layer tra il kernelLinux e il sistema hardware:
RTHAL (Real-Time Hardware AbstractionLayer).

Versione estesa di RTHAL: ADEOS (Adaptive Domain Environment for
Operating Systems)

Racchiude tutti i dati e le funzioni temporalmente critiche del kernel in
un’unica struttura

Sostituisce le operazioni sulle strutture originali con operazioni su
puntatori RTHAL

I puntatori RTHAL sono modificabili dinamicamente. Se RTAI non è
attivo puntano alle strutture originali di Linux, se RTAI è attivo puntano
alle strutture del kernel real-time

Linux non ha più il controllo sull’abilitazione / disabilitazionedelle
interruzioni.
Architettura di RTAI

Real Time HAL (RTHAL) non fornisce servizi real-time: ha la sola
funzione di intercettare le chiamate al kernelLinux.

Le chiamate sono redirette alle strutture puntate da RTHAL.

RTAI non attivo
 Funzionamento normale di Linux.

RTAI attivo
 Linux è gestito come un processo a bassa priorità.

Quindi RTAI può essere attivato o disattivato a piacere?

SÌ…perché RTAI è disponibile come modulo kernel di Linux.

Permette di estendere dinamicamente le funzionalità del kernel senza
dover essere caricato al boot di sistema.
Architettura di RTAI

Scopo: realizzare un ambiente flessibile per condividere risorse
hardware tra più sistemi operativi o più istanze di uno stesso SO

La realizzazione consiste in un microkernel che gestisce la
comunicazione con i diversi domini (es. SO) installati

La gestione delle interruzioni è implementata con uno schema a
pipeline in cui ogni stadio rappresenta un dominio

Ogni interruzione è propagata alla pipeline, ogni stadio può:




Accettare l’interrupt, gestirlo, scegliere se propagarlo o terminarlo
Ignorare l’interrupt, non accettarlo immediatamente ma gestirlo al
momento opportuno, scegliere se propagarlo o terminarlo
Scartare l’interrupte propagarlo
Terminare l’interrupts enza propagarlo ulteriormente
Architettura di RTAI
RTAI: scheduling

Ogni possibile configurazione dello scheduler è
adatta ad una specifica combinazione di hardware e
requisiti delle applicazioni

RTAI permette una gestione full-preemptable dei
processi, in funzione delle loro priorità.




Funzione del numero di processori presenti
Scelta della modalitàdi funzionamento dello Scheduler
Scelta della politica di scheduling
Configurazione dello scheduler
RTAI: scheduling

Uniprocessor Scheduler(UP): Utilizzabile nei sistemi monoprocessore

Symmetric Multiprocessor Scheduler (SMP): In un sistema
multiprocessore permette una distribuzione di carico simmetrica.

Ogni processo di default può essere assegnato a qualsiasi processore;
per ottimizzare l’esecuzione è possibile imporre l’esecuzione di un
processo su una CPU o su un insieme ristretto di CPU

Multi Uniprocessor Scheduler(MUP)


In un sistema multiprocessore impone ad ogni processo l’esecuzione
su una CPU stabilita al momento della sua creazione. Meno flessibile
ma più efficiente di SMP
La scelta dello scheduler in funzione dell’hardware in uso impatta su
quale modulo kernel viene caricato con RTAI.
RTAI: scheduling

Periodic mode:



One-shot mode



Esegue lo scheduler periodicamente : il timer viene settato una sola
volta all’inizio dell’esecuzione
Il periodo dei processi deve essere multiplo esatto del periodo dello
scheduler, in caso contrario il periodo dei processi viene
approssimato al multiplo del periodo dello scheduler più vicino
(introduce jitter di attivazione)
Lo scheduler viene eseguito in maniera non periodica. Il timer deve
essere settato ogni volta in base al processo prioritario
Permette una gestione più flessibile delle temporizzazioni di tutti i
processi a costo di un maggiore overhead dovuto alla necessità di
riprogrammare il timer al termine di ogni periodo
Occorre scegliere la temporizzazione con cui lo scheduler viene
eseguito.
RTAI: politiche di scheduling

FIFO


Round-Robin (RR)


Il processo attivo a priorità più alta ottiene il controllo della CPU
fino a quando la rilascia volontariamente oppure diventa attivo un
processo a prioritàmaggiore
Il processo attivo a priorità più alta ottiene il controllo della CPU
per un determinato intervallo di tempo, al termine del quale il
controllo passa ad un altro processo allo stesso livello di
priorità(se presente). Un processo può subire preemption da
parte di un processo a prioritàmaggiore
RTAI integra primitive che associate alla politica FIFO
permettono una semplice implementazione degli algoritmi di
scheduling Rate Monotonic - Priority Ordered – Earliest
Deadline First.
RTAI: politiche di IPC

Real-time fifos


Shared Memory


Possibilitàdi inviare messaggi sia in maniera asincrona che sincrona
(RPC) tra processi RT
Mailboxes


Condivide aree di memoria tra processi RT e processi Linux
Messages


Meccanismo di base per scambiare dati in modo asincrono tra
processi real-time e processi Linuxnon real-time
Permettono di inviare/ricevere messaggi di qualsiasi dimensione,
ordinati per prioritào per istante di arrivo, tra processi RT e processi
Linux
Semaphores

Permettono di sincronizzare i processi nell’accesso a risorse
condivise evitando inversioni di priorità incontrollate
Moduli RTAI

RTAI presenta un certo numero di moduli:
–
rtai_hal
–
rtai_sched
–
rtai_fifos
FIFO
–
rtai_shm
memoria condivisa
–
rtai_lxrt
LXRT
intercetta gli interrupt
gestione dei task: schedulazione, messaggi,
semafori,...IPC
task in tempo reale nello spazio utente:
permette di sviluppare processi real time usando
le API RTAI da spazio utente
–

rtai_pthread
Thread Posix
Questi moduli devono essere inseriti a seconda delle esigenze
–
insmod rtai_hal
–
insmod rtai_sched ...
Altra vista della architettura
Processi
Linux
RT
FIFO
Processi
Linux
Kernel Linux
RT
task
RT
task
Real time kernel (RTHAL/ADEOS
Programmazione in RTAI

Struttura: utilizza 3 parti principali scritte
dall’utente



Funzione che inizializza il sistema, definisce le
caratteristiche dei vari task e IPC
Definizione della funzione real time
Funzione che rilascia le risorse
Programmazione in RTAI

Esempio della funzione di inizializzazione
int init_module(void)
{
RTIME tick_period,
now;
//crea la fifo
rtf_create(0, 1000*sizeof(struct msg_t));
//inizializza la struttura rt
// rt_task_init( , , , stacksize, priorità, uso fpu, signal function)
rt_task_init(&hiprio_task, task_body, ‘F’, 2000, 0, 0, 0);
//start rt_timer
rt_set_oneshot_mode();
tick_period = start_rt_timer(nano2count(TIMERTICKS));
//start the rt-task
now = rt_get_time();
rt_task_make_periodic(&hiprio_task, now+tick_period, 12*tick_period);
return 0;
}
Programmazione in RTAI

Definizione di un task (thread in tempo reale):
int rt_task_init(RT_TASK *task, void(*rt_thread)(int), int data, int stack_size,
int priority, int uso_fpu, void(*signal)(void));



Attenzione: definisce il task, non l’esegue!
Il task si trova nello stato SUSPENDED
Argomenti della funzione:







Primo argomento: descrittore del task
Secondo argomento: entry point della funzione
Terzo argomento: un intero passato dal genitore al thread
Quarto argomento: dimensione dello stack
Quinto argomento: priorità (RT_LOWEST_PRIORITY – 0)
Sesto argomento: flag per l’uso della fpu
Settimo argomento: funzione per gestire il segnale inviato quando il
thread diventa corrente
Programmazione in RTAI

Attivazione di un task (messa in esecuzione): due modalità

Mediante la definizione di task periodico
int rt_task_make_periodic(RT_TASK *task, RTIME start_time, RTIME period);

Mediante la messa in stato di pronto
int rt_task_resume(RT_TASK *task);

L’istante di esecuzione è dato con


start_time (valore assoluto misurato in clock ticks)
start_delay (valore relativo al tempo corrente e misurato in
nanosecondi)
Programmazione in RTAI

Gestione della schedulazione:

Nel caso di task periodico
int rt_task_wait_period(void);
sospende l’esecuzione del thread corrente fino al prossimo periodo
Nel caso di task aperiodico
int rt_task_yield(void);

int rt_task_suspend(RT_TASK *task);
task_yield ferma il task corrente e lo mette alla fine della coda; lo
schedulatore attiva il primo thread alla stessa priorità
task_suspend sospende l’esecuzione, che verrà ripresa con resume o
con make_periodic
Programmazione in RTAI

Funzioni di utilità per la schedulazione:
void rt_sleep(RTIME delay);
void rt_sleep_until(RTIME time);
sospendono il thread in esecuzione e lo mettono in stato DELAYED
void rt_busy_sleep(int nanosecs);
addormenta in thread mandando in loop la CPU per il tempo indicato
void rt_sched_lock(void);
void rt_sched_unlock(void);
blocca/sblocca lo schedulatore pe evitare corse critiche
int rt_get_prio(RT_TASK *task);
int rt_change_prio(RT_TASK *task, int priority;
determina/setta la priorità di base
int rt_get_inher_prio(RT_TASK *task);
Determina la priorità ereditata a causa dell’accesso a risorse condivise (protocolli priority
inheritance)
Programmazione in RTAI

Altre funzioni di utilità per la schedulazione:
int rt_get_task_state(RT_TASK *task);
RT_TASK *rt_whoami(void);
int rt_task_use_fpu(RT_TASK *task, int use_fpu_flag);
int rt_task_delete(RT_TASK *task);
rimuove is task dal sistema
Programmazione in RTAI

Esempio della funzione di rilascio risorse
int cleanup_module(void)
{
//ferma il timer
stop_rt_timer();
rt_busy_sleep(10000000);
//chiude la fifo
rtf_destroy(0);
//cancella la struttura rt
rt_task_delete(&hiprio_task);
}
Programmazione in RTAI
La gestione del timer
 Modalità di funzionamento:
 One-shot: temporizzazioni arbitrarie
void rt_set_oneshot_mode(void);
I task possono essere eseguiti in istanti qualsiasi
 Periodic: tutti i tempi del sistema diventano multipli del periodo
di base del timer
void rt_set_periodic_mode(void);

Ogni richiesta non multiplo del periodo viene soddisfatta nel
periodo più vicino. È il default.
 Attivazione/fermo del timer:
RTIME start_rt_timer(int period);//se modalità
aperiodica il periodo viene ignorato
void stop_rt_timer(void);
Programmazione in RTAI
La gestione del timer
 Modalità di funzionamento:
 One-shot: temporizzazioni arbitrarie
void rt_set_oneshot_mode(void);
I task possono essere eseguiti in istanti qualsiasi
 Periodic: tutti i tempi del sistema diventano multipli del periodo
di base del timer
void rt_set_periodic_mode(void);

Ogni richiesta non multiplo del periodo viene soddisfatta nel
periodo più vicino. È il default.
 Attivazione/fermo del timer:
RTIME start_rt_timer(int period);//se modalità
aperiodica il periodo viene ignorato
void stop_rt_timer(void);
Programmazione in RTAI: IPC

RTAI usa sistemi di IPC simili a Linux ma implementati
separatamente:
rt_fifo: scambio dati tra i thread in tempo reale, tra processi Linux,
shared memory, tra thread in tempo reale e processi Linux
 mailbox
 semafori
 RPC

Programmazione in RTAI: IPC

rt_fifo

Per creare una rt_fifo:
int rtf_create(unsigned int fifo, int size);
Per dimensionare una rt_fifo:
int rtf_resize(int fd, int size);


Per aprire una rt_fifo dallo spazio utente si usa open();
Per aprire una rt_fifo dallo spazio kernel si usa:
int rtf_open_sized(const char *dev, int perm, int size);
Le rt_fifo possono essere associate a dei command handler che vanno
in esecuzione ogni volta che un processo nello spazio utente esegue
una read() o una write() sulla fifo:

int rtf_create_handler(unsigned int minor, int (*handler)(unsigned int fifo)););
Programmazione in RTAI: IPC

rt_fifo: esempio d’uso dei command handler
int rtf_create_handler(fifo_numver, X_FIFO_HANDLER(x_handler);
con, ad esempio, come x_handler:
int x_handler(unsigned int fifo, int rw)
{
if(rw==‘r’){
//quello che bisogna fare in relazione ad una read
}
else{
//quello che bisogna fare in relazione ad una write
}
}
Programmazione in RTAI: IPC

rt_fifo: per evitare bloccaggi indeterminati
int rtf_read_all_at_once(int fd, void *buf, int count);
int rtf_read_timed(int fd, void *buf, int count, int ms_delay);
int rtf_write_timed(int fd, void *buf, int count, int ms_delay);

rt_fifo: uso dei semafori
int rtf_sem_init(unsigned int fifo, int value);
int rtf_sem_wait(unsigned int fifo); //solo dallo spazio utente
int rtf_sem_trywait(unsigned int fifo); //solo dallo spazio utente
...
Programmazione in RTAI: IPC

IPC memoria condivisa (shared memory)



Per trasferire dati tra processi e task
Naturalmente sono molto veloci
Svantaggi:





non essendo serializzati necessitano di un protocollo di accesso
il bloccaggio tra processi e task non è supportato  bisogna gestire il
trasferimento con un metodo
non è garantita la mutua esclusione processi/task
Non è possibile rilevare letture/scritture interrotte
Tipi di shared memory:


Mbuff: condivisione procesi/thread (cioè spazio utente/spazio kernel) senza
richiedere RTAI
Shmem: condivisione procesi/thread (cioè spazio utente/spaziokernel) che
dipende profondamente da RTAI
Programmazione in RTAI: IPC

mbuff:


Implementata come device driver: device /dev/mbuff
Per accedere alla memoria condivisa dallo spazio utente/kernel:
void *mbuff_alloc(unsigned long name, unsigned int size);
Per rilasciare la memoria:
void mbuf_free(int name, void *mbuf);
Programmazione in RTAI: IPC

shmem:


Implementata come device driver: device /dev/rtai_shm
Per accedere dallo spazio utente:
void *rtai_malloc(unsigned long name, int size);

Per rilasciarla:
void rtai_free(int name, void *adr);

Per accedere dallo spazio kernel:
void *rtai_malloc(unsigned long name, int size);

Per rilasciarla:
void rtai_free(int name, void *adr);
Scarica

Introduzione ad RTAI - Università degli Studi di Trieste