Facoltà di Ingegneria
Corso di Studi in Ingegneria Informatica
Elaborato finale in Sistemi real-time
Analisi del sistema operativo VxWorks per lo sviluppo di
applicazioni real-time
Anno Accademico 2012/2013
Candidato:
Alessio Nisini
matr. N46000045
Indice
Introduzione
5
Capitolo 1. Panoramica generale
6
1.1
1.2
1.3
Caratteristiche chiave
Sistema host e target
Componenti e profili
6
7
8
Capitolo 2. Processi real-time
2.1
2.2
2.2.1
2.2.2
10
Creazione dei processi real-time
Modelli di memoria virtuale
Modello flat
Modello overlapped
10
12
12
13
Capitolo 3. Task real-time
3.1
3.2
3.3
3.4
14
Creazione dei task
Area stack di un task
Hook routine
Task base
14
15
15
16
Capitolo 4. Multitasking
4.1
4.2
4.2.1
4.2.2
4.3
4.3.1
4.3.2
4.3.3
4.3.4
4.3.5
4.3.6
18
Stati dei task
Scheduling
Scheduler VxWorks tradizionale
Scheduler VxWorks di thread POSIX
Intertask ed interprocess communication
Memoria condivisa
Semafori
Code di messaggi
Pipe
Eventi WxWorks
Segnali
18
20
21
23
24
24
25
27
28
29
30
III
Capitolo 5. I/O system
5.1
5.2
5.3
31
I/O base
I/O bufferizzato
I/O asincrono
32
33
33
Capitolo 6. File system
35
Conclusioni
Bibliografia
38
39
IV
Introduzione
In un recente passato, alla domanda: “cos’è un sistema di elaborazione?” la naturale
risposta sarebbe stata: “un personal computer”.
Questa risposta è ormai superata, infatti, la maggior parte dei sistemi di elaborazione, oggi,
è costituita dai sistemi embedded, presenti su un numero elevatissimo di apparecchi, che la
maggioranza di noi utilizza senza averne piena coscienza.
A sua volta, la maggior parte dei sistemi embedded è di natura real-time.
Negli ultimi anni, la complessità di tali sistemi è cresciuta notevolmente, sia in
conseguenza delle più disparate esigenze applicative, sia della complessità dei dispositivi
hardware che si sono resi disponibili.
Questa crescente complessità nega la possibilità agli sviluppatori di affrontare le
problematiche applicative direttamente sull’hardware e rende necessario l’uso dei sistemi
operativi real-time.
Esistono numerosi RTOS, di natura aperta come RT-LINUX, RTAI, RTEMS o proprietari
quali ITRON, QNX, OSE, VxWorks; ognuno di questi ha caratteristiche peculiari che lo
rendono più o meno adatto a determinate esigenze.
In questo elaborato concentreremo la nostra attenzione sul sistema operativo VxWorks
partendo dalle caratteristiche che lo hanno reso noto e soffermandoci su interessanti aspetti
quali la gestione dei processi e dei task, lo scheduling e l’interprocess comunication fino a
giungere alla gestione dell’I/O e dei file system.
5
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Capitolo 1
Panoramica generale
VxWorks è un sistema operativo real-time, conforme allo standard POSIX 1003.1b,
sviluppato da Wind River System ad Alameda, California, USA, la cui prima release risale
al 1987, quella attuale è la 6.9.
Trova applicazione soprattutto nell’industria aereospaziale, nel settore della robotica e nel
settore dell’automotive, come dimostra la sua presenza sull’ iDrive system della BMW,
sul sistema di navigazione Siemens VDO, su alcuni veicoli spaziali quali Spirit and
Opportunity, Phoenix, Clementine ed altri.
Ai giorni nostri, VxWorks, è utilizzato su più di un miliardo di sistemi real-time e supporta
praticamente qualsiasi CPU, non è quindi errato affermare che è il sistema operativo per lo
sviluppo di applicazioni real-time più venduto al mondo.
1.1 Caratteristiche chiave
Le caratteristiche fondamentali che hanno reso VxWorks celebre sono:
• Il supporto al multi-core e al multi-OS: consente a VxWorks di supportare varie tipologie
di configurazione quali la gestione dei processori simmetrica (SMP) o la gestione
asimmetrica (AMP): la prima consente l’uso di più CPU, con la medesima architettura,
che condividono la memoria e collaborano dividendosi il carico di lavoro; la seconda
6
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
consente l’uso di più CPU, non necessariamente uguali, ognuna con un proprio spazio
indirizzi ed eventualmente gestita da un sistema operativo ad essa dedicato; quest’ultima
configurazione è utilizzata quando risulta essere conveniente distribuire specifiche attività
su componenti differenti.
• La scalabilità: è offerta una vasta gamma di configurazioni possibili, che variano dalla
leggerezza e semplicità necessarie ad un sistema snello, alla ricchezza di funzionalità di un
sistema basato su architetture a 64 bit, multi-core, orientato alle più alte esigenze.
• La sicurezza: numerose certificazioni garantiscono la conformità agli standard di
sicurezza globale, includendo RTCA DO-178B, EUROCAE ED-12B and IEC 61508.
Fornisce anche un multilevel secure (MLS), che consente alle applicazioni di processare
informazioni con differenti livelli di sicurezza.
1.2 Sistema host e target
VxWorks, adoperato principalmente nell’ambito dei sistemi integrati, utilizza un metodo
di compilazione cross-compiling che permette allo sviluppatore di generare codice su un
qualsiasi macchina host, ad esempio un PC Linux, Windows, Solaris, e compilare
direttamente su uno specifico hardware target, sul quale non è conveniente programmare.
La programmazione di applicazioni real-time sulla macchina host è supportata da Wind
River fornendo una suite basata su Eclipse, chiamata Wind River Workbench,
la quale minimizza la necessità di interfacciamento al sistema target.
Il sistema target può essere anche simulato tramite Wind River VxWorks Simulator,
consentendo allo sviluppatore di testare applicazioni VxWorks sul sistema host ed
eliminando la necessità di un target hardware in fase di sviluppo e di test.
Sul sistema target invece VxWorks utilizza i cosiddetti board support package (BSP), i
quali forniscono un’interfaccia tra il sistema operativo e l’hardware sottostante e
garantiscono la portabilità; è infatti possibile utilizzare VxWorks su più hardware
differenti senza dover necessariamente modificare il kernel, a patto di una corretta
configurazione dei BSP.
Un BSP è tipicamente composto da un codice sorgente scritto in C o in assembly, uno o
7
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
più header file, un makefile e un target.ref o target.nr che contengono la documentazione
specifica per il BSP.
1.3 Componenti e profili
La scalabilità caratteristica di VxWorks, in termini di modularità ed estensibilità, è
garantita attraverso l’implementazione di specifici componenti.
Un componente VxWorks è l’unità base per fornire quelle funzionalità con le quali
VxWorks può essere configurato; alcuni di questi dipendono da altri componenti che
devono essere inclusi nelle configurazioni del sistema operativo, altri sono indipendenti.
Il Workbench fornisce funzionalità per configurare VxWorks con i componenti selezionati
e determinare le relazioni di dipendenza fra essi, identificati convenzionalmente mediante
un nome che comincia con la parola INCLUDE (ad esempio INCLUDE_RTP per il
supporto ai processi real-time).
Congiuntamente ai componenti vengono spesso utilizzati i cosiddetti profili, utili per
garantire un gruppo base di funzionalità alternative a quelle presenti nella configurazione
di default, all’atto dell’installazione di VxWorks.
Tra i vari profili esistenti citiamo i tre che consentono di diminuire la grandezza di default
del sistema operativo; questi profili non supportano i servizi di networking:
• PROFILE_MINIMAL_KERNEL: fornisce solamente i servizi indispensabili al
funzionamento del sistema; è composto da un microkernel e da un supporto base alla CPU
e al BSP, consente il mutitasking e la gestione delle interruzioni, ma non supporta
l’allocazione dinamica della memoria.
• PROFILE_BASIC_KERNEL: aggiunge al profilo minimale supporto alle code di
messaggi, allocazione dinamica della memoria e un sistema I/O base.
• PROFILE_BASIC_OS: completa il sistema I/O e aggiunge la gestione di variabili di
ambiente, segnali, pipe e di un coprocessore; questo profilo è molto simile alla
configurazione VxWorks 5.5, ma senza lo stack network e senza tool di debugging.
8
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
La seguente figura illustra le relazioni fra i tre profili e le funzionalità che forniscono.
Figura 1: Profili in VxWorks
Il più piccolo tra questi può generare un’immagine del sistema di 100KB o meno.
I profili non sono monolitici e ognuno di essi può essere la base per ulteriori funzioni
addizionali che possono essere aggiunte tramite componenti VxWorks o altri profili.
9
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Capitolo 2
Processi real-time
I Processi real-time VxWorks (RTP) sono per molti aspetti simili ai processi di altri
sistemi operativi, quali UNIX e Linux. Il modo in cui sono creati, messi in esecuzione e
terminati sarà di facile comprensione per chi è conscio del modello di processo UNIX.
Essi sono stati introdotti a partire dalla versione 6.0, in precedenza il funzionamento del
sistema si basava esclusivamente su task.
In tutto il ciclo di vita del processo è sempre garantito il determinismo, indispensabile per i
sistemi real-time.
2.1 Creazione dei processi real-time
La creazione dei processi real-time è divisa in due parti e separa la creazione di un'istanza
del processo dal caricamento e dall'esecuzione della relativa applicazione.
La prima fase consiste nella chiamata rtpSpawn() nel contesto del task padre, questa
genera l'oggetto del processo nel sistema, alloca memoria virtuale e fisica, e crea il task
iniziale del processo.
La seconda fase è a carico del task iniziale del processo appena creato, il quale carica
l'eseguibile per intero e avvia la main routine.
10
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Questo approccio garantice il determinismo in due modi:
• La fase di creazione del processo (rtpSpawn() task) e la fase di caricamento
dell'applicazione (initial task) sono indipendenti: un processo sarà creato in maniera
discreta e deterministica senza tener conto dell’applicazione ad esso relativa.
Tale meccanismo di indipendenza offre allo sviluppatore la possibilità di assegnare una
priorità appropriata al task a seconda dall'applicazione.
• L'eseguibile dell'applicazione è caricato per intero quando il processo è creato, ciò
garantisce determinismo evitando imprevisti tempi di caricamento durante l'esecuzione.
Il nome del task iniziale del processo è basato sul nome del file eseguibile con le seguenti
modifiche:
• La lettera "i" è prefissa
• La prima lettera del nome del file è maiuscola
• L'estensione del file è rimossa
Ad esempio se l'applicazione "app.vxe" è in esecuzione, il nome del task iniziale del
processo sarà "iApp".
Un processo VxWorks può essere avviato nei seguenti modi:
• interattivamente dalla shell
• automaticamente nella fase di boot
• in modo programmato da applicazioni o dal kernel
VxWorks gestisce una gerarchia di processi caratterizzati da relazioni padre-figlio.
Ogni processo creato dal kernel è figlio del kernel.
11
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Un processo VxWorks eredita alcuni attributi dal padre: descrittori dei file, che indicano la
possibilità di accedere al medesimo file, e maschere di segnali.
Se il processo è figlio del kernel eredita solo i tre descrittori dei file standard (stdin, stdout,
stderr) e tutti i segnali saranno sbloccati poiché la maschera dei segnali ereditata sarà 0.
Invece le variabili di ambiente non sono ereditate, ma il padre potrà passare al processo
figlio il suo ambiente o una parte di esso attraverso diverse procedure.
Differenza sostanziale nella creazione dei processi tra VxWorks e lo standard POSIX è
che VxWorks non consente la creazione di processi tramite le primitive fork() ed exec().
2.2 Modelli di memoria virtuale
Ogni processo possiede il proprio spazio di indirizzamento che contiene il programma
eseguibile, i dati del programma, l'area stack per ogni task, l'area heap e le risorse
necessarie per la gestione del processo stesso.
I processi VxWorks possono operare con due differenti modelli di memoria virtuale
mutuamente esclusivi: modello flat (fisso), modello overlapped (sovrapposto).
2.2.1 Modello flat
È il modello di memoria virtuale di default e non richiede configurazioni specifiche. Con
questo modello ogni processo VxWorks possiede la propria regione di memoria virtuale,
quindi i processi non sono sovrapposti nella memoria.
L'utilizzo del modello flat comporta i seguenti vantaggi:
• velocità nei cambi di contesto
• semplicità nel debugging, poiché gli indirizzi per ogni processo sono univoci
• flessibilità nel metodo di programmazione, consentendo alle applicazioni VxWorks di
funzionare sia con che senza il supporto di una MMU.
Quest'ultima caratteristica facilita il determinismo per i processi hard real-time rendendo
possibile la disabilitazione della MMU.
12
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Per contro, l'utilizzo del modello di memoria virtuale fisso costringe alla rilocazione dei
file eseguibili e ciò comporta un tempo di caricamento maggiore rispetto a quello che
avremmo utilizzando il modello sovrapposto; inoltre il modello flat non permette allo
sviluppatore di scegliere una specifica area di memoria virtuale dove il codice delle
applicazioni risiederà, questa sarà scelta dall’algoritmo automatico best-fit.
2.2.2 Modello overlapped
È opzionale ed un suo utilizzo implica necessariamente l'uso della MMU. Con questo
modello tutte le applicazioni VxWorks condividono un range comune di indirizzi di
memoria virtuale nel quale risiede l’insieme delle informazioni relative alle applicazioni
stesse.
Il modello overlapped porta i seguenti vantaggi:
• Un più rapido tempo di caricamento (all'incirca tra il 10 e il 50 percento) quando viene
usato un indirizzamento assoluto dovuto all'assenza della fase di rilocazione
• Un maggior controllo della memoria virtuale, poiché è l'utente che decide l'area dove le
informazioni relative alle applicazioni risiederanno
• Una maggior efficienza della memoria virtuale ottenuta riducendo la possibilità di
frammentazione della memoria.
13
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Capitolo 3
Task real-time
I task di VxWorks sono l'unità base che rappresenta codice in esecuzione nel sistema
stesso. Sono generati e messi in esecuzione dai processi a seconda delle necessità; non c’è
un limite al numero di task in un processo, esso dipende esclusivamente dall’ammontare
della memoria disponibile.
3.1 Creazione dei task
Per creare un singolo task si utilizza la routine taskSpawn(), presente nella libreria
taskLib, gli argomenti che devono essere passati sono: il nome del task, la sua priorità, le
opzioni, la grandezza dello stack, l'indirizzo della main routine e 10 argomenti da passare
alla main routine; la sintassi è quindi la seguente:
id = taskSpawn ( name, priority, options, stacksize, main, arg1, ... , arg10 );
Alternativamente alla routine taskSpawn(), che crea e attiva un nuovo task, è consentito
l’uso di:
• taskCreate(): crea, ma non attiva un nuovo task
• taskOpen(): apre un task oppure opzionalmente lo crea se non esiste
• taskActivate(): attiva un task inizializzato
14
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Wind River raccomanda di usare le routine taskCreate() e taskActivate() solo quando le
necessità di controllo sull'allocazione e sull'attivazione sono stringenti.
I task in VxWorks possono essere creati o come oggetti privati, accessibili solo all’interno
dello spazio di memoria in cui sono stati creati (kernel o processo), o pubblici, accessibili
ovunque nel sistema.
3.2 Area stak di un task
Alla creazione di un task deve essere specificata la grandezza dello stack riservato ad esso;
determinare tale valore in maniera corretta può essere arduo o non immediatamente
possibile. Per evitare situazioni di overflow e corruzione dei dati è opportuno riservare
un’area stack molto più grande di quella prevista, in seguito monitorarla dalla shell tramite
checkStack() o ti() e infine, dopo aver determinato l’effettivo utilizzo, correggerne la
grandezza.
In caso di utilizzo dell’MMU essa è arrotondata a un multiplo della grandezza delle
pagina.
Inoltre l’area stack di un task può essere protetta da una guard zone, inclusa tramite il
componente INCLUDE_PROTECT_TASK_STACK; questa impedisce ad un task di
superare la fine dello stack che gli è stato concesso, prevenendo corruzione di dati o di
altri stack.
3.3 Hook routine
Per estendere il set di funzionalità relative ai task nel sistema, VxWorks fornisce le
cosiddette hook routine, invocate ogniqualvolta un task è creato, quando avviene un
cambio di contesto o quando un task è cancellato. Ad esempio:
• taskCreateHookAdd(): aggiunge una routine nel sistema che dovrà essere chiamata alla
creazione di ogni task
• taskCreateHookDelete(): aggiunge una routine nel sistema che dovrà essere chiamata
15
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
alla cancellazione di ogni task
Queste e altre routine per la gestione dei task hook sono presenti nella libreria
taskHookLib.
3.4 Task base
A seconda della configurazione, nella fase di boot, VxWorks avvia una varietà di task di
sistema che sono sempre in esecuzione (demoni). Vediamo i principali:
• Root Task: il tRootTask è il primo task eseguito dal kernel, questo genera altri task come
il logging task, l'exception task, il network task; normalmente il root task termina ed è
cancellato quando completa tutte le inizializzazioni.
• Logging Task: il tLogTask è usato dai moduli VxWorks per la gestione dei messaggi di
log in modo da consentire ai task di non essere ritardati da operazioni di I/O sincrone.
• Exception Task: il tExcTask supporta la libreria per la gestione delle eccezioni di
VxWorks e si occupa di eseguire le azioni necessarie nei casi di eccezioni generate
dall'esecuzione del codice dei task, in opposizione alle routine di interrupt che reagiscono
ai segnali provenienti dall'ambiente, portando a termine funzioni che non sono servite dal
gestore interruzione. È anche usato per azioni che non possono essere compiute
nell'attuale contesto del task, come ad esempio l'auto-terminazione dei task. L’exception
task deve avere la priorità massima nel sistema.
• Network Task: il tNet0 è un task che consente ai processi di utilizzare le risorse della rete
in VxWorks ed è principalmente usato dai driver network. Nei sistemi che sono
configurati con più network daemon essi prendono il nome tNetn con
n
costituito da un
identificativo numerico.
16
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
• Kernel Shell: se è stata inclusa la kernel shell nelle configurazioni di VxWorks, questa è
generata come un task e prende il nome di tShellnum, dove num indica il numero della shell,
poiché più shell possono essere attive contemporaneamente. Qualsiasi routine o task
invocato dal kernel shell è eseguito nel contesto del tShellnum anziché essere creato.
• Job Task: il tJobTask esegue i cosiddetti jobs, ossia chiamate di funzioni, per conto dei
task. Questo esegue a priorità 0 quando è in attesa di una richiesta, e automaticamente
cambia la propria priorità facendola corrispondere a quella del task che ha generato la
richiesta quando dovrà servirla.
17
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Capitolo 4
Multitasking
Lo sviluppo multitasking consente ad un’applicazione real-time di essere costituita da una
serie di task indipendenti, ognuno caratterizzato da un proprio flusso di esecuzione e da un
set di risorse di sistema.
Il Multitasking fornisce il meccanismo fondamentale di un'applicazione per garantire
controllo e capacità di reazione a eventi discreti del mondo reale.
4.1 Stati dei task
Il kernel mantiene lo stato corrente di ogni task nel sistema, il quale potrà variare a seguito
dell’esecuzione di determinate routine.
All’atto della creazione attraverso taskSpawn(), il task assume immediatamente lo stato
ready, mentre l’utilizzo di taskCreate() o taskOpen() genererà un task in stato suspended,
esso potrà essere attivato immediatamente tramite taskActivate() che lo porterà nello stato
ready.
Elenchiamo adesso gli stati fondamentali dei task:
• READY: il task non è in attesa di nessuna risorsa se non della CPU
• PEND: il task è bloccato a causa della non disponibilità di alcune risorse
• DELAY: il task è dormiente per una certa durata
• SUSPEND: il task non è pronto per essere eseguito
18
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
• STOP: il task è stato fermato dal debugger
È importante notare che lo stato dei task è additivo: un task può trovarsi simultaneamente
in più stati, ad esempio DELAY + S indica che il task è sia nello stato delay che in quello
suspend.
La seguente figura mostra una semplice illustrazione delle transizioni dei task specificando
inoltre quali sono le procedure che possono generare tali transizioni.
Figura 2: stati dei task e transizioni
19
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
4.2 Scheduling
Per implementare una gestione multitasking è necessario uno schedulatore che assegna la
CPU ai task pronti. VxWorks fornisce le seguenti opzioni di scheduling:
• Lo schedulatore VxWorks tradizionale, basato su priorità con il supporto dell'algoritmo
di schedulazione Round-Robin
• Lo schedulatore VxWorks di thread POSIX, appositamente progettato per l’utilizzo di
thread nei processi
• La possibilità per il programmatore di sviluppatore il proprio schedulatore
Nessuna delle opzioni consente la schedulazione di processi RTP, le uniche entità
schedulabili sono i task e i thread.
Indipendentemente dall’opzione scelta, Vxworks utilizza un algoritmo di scheduling
basato su priorità, suddivise in 256 livelli numerati da 0 a 255 dove 0 indica il processo a
priorità maggiore.
Ad ogni task è assegnata una priorità all’atto della creazione, variabile durante il suo ciclo
di vita.
Le funzioni che controllano lo scheduling dei task sono:
• taskPrioritySet(): cambia la priorità di un task
• taskRtpLock(): disabilita il cambio di contesto nel processo
• taskRtpUnLock(): abilita il cambio di contesto nel processo
L'uso della funzione taskPrioritySet() fa si che il task sia posizionato alla fine della coda
dei task pronti relativa al nuovo livello di priorità assegnato.
Le funzioni taskRtpLock() e taskRtpUnLock() garantiscono l'esplicita disabilitazione e
abilitazione dello scheduler; in particolare un task che chiama la taskRtpLock() fa si che
20
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
nessun altro task del medesimo processo possa prelazionarlo, se tale task si blocca o si
sospende allora lo schedulatore manderà in esecuzione il prossimo task a priorità
maggiore.
È importante sottolineare che il blocco della prelazione non previene il cambio di contesto
dovuto al gestore delle interruzioni.
4.2.1 Scheduler VxWorks tradizionale
È lo schedulatore di default ed è incluso nel sistema tramite il componente
INCLUDE_VX_TRADITIONAL_SCHEDULER.
Mantiene una coda per i task ready, gestita con politica FIFO, per ogni livello di priorità.
Quando la CPU è disponibile, essa viene assegnata al task che si trova in testa alla coda a
priorità più alta. La posizione di un task nella coda può variare a seconda delle operazioni
svolte sul task:
• Se il task è prelazionato questo andrà in testa alla coda con la sua stessa priorità.
• Se il task passa nello stato di pended, delayed, suspended oppure stopped sarà rimosso
dalla sua attuale coda, e quando tornerà ad essere ready verrà posizionato alla fine di una
coda scelta in basa alla sua priorità.
• Se la priorità di un task cambia tramite la funzione taskPrioritySet(), sarà inserito alla
fine della relativa coda.
• Se è chiamata la funzione taskRotate(), il task sarà spostato dalla testa all'ultima
posizione della sua coda.
Poiché, come precedentemente affermato, lo schedulatore VxWorks tradizionale è uno
schedulatore con prelazione basata su priorità, quando è presente un task ready con
priorità maggiore di quello al momento in esecuzione, quest'ultimo sarà prelazionato e il
suo contesto salvato e sostituito con quello del task a priorità maggiore. L'esempio in
figura mostra il task t1 prelazionato a favore di t2 a sua volta prelazionato a favore t3.
Quando t3 termina, t2 riprende ad eseguire seguito a sua volta da t1.
21
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Figura 3: scheduling prioritario
Lo svantaggio di questo algoritmo di scheduling si manifesta quando sono presenti più
processi pronti con il medesimo livello di priorità: dopo aver assegnato la CPU a uno dei
task questo la manterrà per tutto il tempo necessario, rischiando di ritardare
eccessivamente l'esecuzione degli altri task con la medesima priorità.
Questo problema è risolto affiancando all'algoritmo di scheduling basato su priorità quello
Round-Robin; viene quindi assegnato ad ogni task un quanto di tempo time-slice entro cui
puo mantenere la CPU.
Questa politica di sheduling non va a intaccare la schedulazione di tipo prioritario
precedentemente descritta, infatti, in ogni istante, indipendentemente dal quanto di tempo,
un processo può essere interrotto a favore di un altro a priorità maggiore; se ciò accade il
processo che è stato prelazionato riprenderà l'esecuzione in seguito e gli verrà assegnato il
quanto di tempo residuo.
La seguente figura mostra il contributo dell’algoritmo Round-Robin alla schedulazione di
tipo prioritario.
22
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Figura 4: scheduling prioritario con Round-Robin
L'algoritmo di scheduling Round-Robin è quindi usato per schedulare task che hanno la
stessa priorità, questo è abilitato dalla chiamata kernelTimeSlice(), che riceve come
argomento la durata del time-slice, se tale valore è 0 allora lo schedulatore Round-Robin
verrà disabilitato.
4.2.2 Scheduler VxWorks di thread POSIX
L’implementazione dello schedulatore di thread POSIX in VxWorks migliora lo scheduler
tradizionale VxWorks e fornisce servizi addizionali di scheduling consentendo
l’esecuzione di thread nei processi.
Lo schedulatore di thread POSIX schedula task e thread in modo pressochè uguale allo
scheduler VxWorks tradizionale, con una differenza nella gestione della priorità tra task e
thread: quando la priorità di un thread è abbassata, lo schedulatore posiziona il thread in
testa alla coda relativa alla nuova priorità; se invece è un task a subire la diminuzione di
priorità questo sarà posizionato alla fine della relativa coda, come avviene nella
schedulazione tradizionale in VxWorks.
23
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Per usufruire dello schedulatore di thread POSIX è necessario includere il componente
INCLUDE_POSIX_THREAD_SCHEDULER.
4.3 Intertask ed interprocess communication
Vediamo adesso quali sono i meccanismi che legano la comunicazione fra task e fra
processi.
VxWorks ne fornisce un ampio set:
• Memoria condivisa
• Semafori
• Code di messaggi e Pipe
• Eventi VxWorks
• Segnali
4.3.1 Memoria condivisa
La comunicazione fra processi avviene attraverso la condivisione un'area accessibile a più
applicazioni real-time, organizzata in un singolo blocco contiguo di memoria virtuale.
La libreria che consente la creazione e gestione di una memoria condivisa è la sdLib e
consente di:
• creare una regione di memoria condivisa
• mappare la regione nel contesto di memoria del processo così che possa accedervi
• cambiare gli attributi di protezione della regione
• eliminare la regione dal contesto di memoria di un processo quando questo non è ha più
bisogno
• cancellare la regione quando essa non è più associata ad alcun processo
Affinchè le applicazioni possano usufruire di una memoria condivisa, il componente
INCLUDE_SHARED_DATA deve essere incluso in VxWorks.
24
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Una regione di memoria condivisa può essere creata con sdCreate() ed è mappata
immediatamente nel contesto di memoria del creatore.
I parametri richiesti per la creazione sono: il nome della regione, la sua grandezza,
l'indirizzo fisico, gli attributi della MMU, e altri due parametri che regolano la persistenza
della regione e la sua accessibilità.
Gli attributi della MMU servono a gestire il tipo di permessi di accesso alla regione
condivisa: read only, read/write, read/execute, read/write/execute
Un processo utente che conosce il nome della regione vi può accedere tramite la funzione
sdOpen().
Le modalità di cancellazione della memoria condivisa variano in base alla presenza
dell'opzione SD_LINGER all'atto della creazione: se non presente la regione è cancellata
quando l'ultimo processo mappato sulla regione chiama la sdUnmap() oppure quando
termina; se presente la regione è cancellata solo quando è chiamata la sdDelete() quando
nessun processo vi è più collegato.
Per evitare di lasciare la memoria condivisa in uno stato inconsistente, bisogna garantire
l'accesso mutuamente esclusivo alla risorsa mediante: la disabilitazione delle interruzioni,
la disabilitazione della prelazione e il blocco delle risorse tramite semafori; quest'ultima
rappresenta sicuramente il miglior approccio.
4.3.2 Semafori
VxWorks affronta la problematica della mutua esclusione nell'accesso ad una risorsa
condivisa e della sincronizzazione di un task con eventi esterni
mediante
l’implementazione di un sistema semaforico ottimizzato, garantendo un veloce e sicuro
meccanismo di comunicazione fra task.
25
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
In base all’utilizzo previsto distinguiamo:
• Semafori binari: i più rapidi e multiuso. Garantiscono la mutua esclusione proteggendo la
risorsa critica con routine di blocco e rilascio e la sincronizzazione bloccando un task fino
al manifestarsi di un evento.
• Semafori mutex: ottimizzati per i problemi inerenti la mutua esclusione, come
l'inversione di priorità o la cancellazione sicura, non consentono sincronizzazione. La
priority inversion è risolta implementando la politica di priority-inheritance tramite
l'opzione SEM_INVERSION_SAFE inserita alla creazione del semaforo; la cancellazione
sicura è risolta con l'opzione SEM_DELETE_SAFE che impedisce ad un task di essere
cancellato quando è situato in un’area critica.
• Semafori di conteggio: configurabili ad un qualunque valore maggiore uguale di 0,
specificato alla creazione.
• Semafori read/write: distinguono l'operazione da eseguire sulla risorsa.
In molti casi VxWorks fornisce un set di operazioni di controllo uniche per tutti i tipi di
semafori, quelle fondamentali sono:
• semTake(): decrementa il valore del semaforo, se questo era 0 blocca il task che l'ha
invocata che assume lo stato pend
• semGive(): incrementa la variabile interna ed eventualmente risveglia un task bloccato
Esistono inoltre funzioni relative a specifici tipi di semaforo, ad esempio:
• Creazione del semaforo: semXCreate() con X che varia in base al tipo di semaforo: B
binario, M mutex, C conteggio, RW read/write
26
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
• Blocco e sblocco di semafori read/write: semRTake(), semWTake(), semRWGive()
Notiamo quindi che un semaforo read/write utilizza delle routine diverse dagli altri
semafori; deve essere, infatti, specificato il tipo di accesso all’atto della chiamata
bloccante. Si ha:
• semRTake(): per operazioni di lettura, è concesso l'uso concorrente della risorsa
• semWTake(): per operazioni di scrittura, è permesso solo l'uso esclusivo della risorsa
All'atto di una semRWGive() sarà data precedenza ai task che hanno fatto richiesta di
accesso in scrittura, indipendentemente dalla priorità dei processi.
All'interfaccia uniforme dei semafori VxWorks aggiunge speciali opzioni:
• timeout: restringe la possibilità di chiamare la semTake() ad uno specifico periodo di
tempo; chiamate al di fuori di tale periodo restituiscono un errore.
• queuing: permette di scegliere il meccanismo di accodamento tra FIFO e prioritario.
• interruptible: un task pendente non può essere interrotto da un segnale, tale
comportamento può cambiare inserendo l'opzione SEM_INTERRUPTIBLE all'atto della
creazione del semaforo.
• VxWorks events: un semaforo appena sbloccato può mandare eventi VxWorks a specifici
task.
4.3.3 Code di messaggi
In VxWorks il meccanismo base di comunicazione fra task in un ambiente
monoprocessore è lo scambio di messaggi; a questo scopo sono messe a disposizione due
librerie: msgQLib creata espressamente per VxWorks e mqPxLib basato sullo standard
POSIX 1003.1b per l'estensione real-time.
27
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Ogni task implementa la gestione delle code di messaggi, tramite le seguenti routine:
• msgQCreate(): alloca ed inizializza una coda di messaggi, richiede come input i seguenti
parametri: il massimo numero di messaggi accodabili, la dimensione massima in byte di
ogni
messaggio,
il
meccanismo
di
gestione
della
coda
(MSG_Q_FIFO
/
MSG_Q_PRIORITY).
• msgQDelete(): termina e dealloca una coda di messaggi.
• msgQSend(): invia un messaggio in una coda, se nessun task attende messaggi, questo è
bufferizzato, altrimenti è mandato al primo task in attesa sulla coda.
• msgQRecive(): riceve un messaggio, se presente, da una coda; altrimenti si blocca e
viene posto nella coda dei task che attendono messaggi.
Nella routine msgQSend() è possibile specificare la priorità del messaggio mediante le
opzioni MSG_PRI_NORMAL e MSG_PRI_URGENT, rispettivamente il messaggio sarà
posto alla fine o all'inizio della coda.
Come per i semafori, un task in attesa su una coda di messaggi non è può essere interrotto
a meno che la coda non sia stata creata con l'opzione MSG_Q_INTERRUPTIBLE.
Possono inoltre essere inviati eventi VxWorks a specifici task, quando un messaggio
giunge in una coda sulla quale non c'è un task in attesa.
Per utilizzare i servizi offerti dalle code di messaggi, VxWorks include il componente
INCLUDE_MSG_Q.
4.3.4 Pipe
Sono dispositivi virtuali I/O controllati dal driver pipeDrv e costituiscono un'alternativa
alle code di messaggi usate per l' I/O system di VxWorks.
La routine pipeDevCreate() crea una pipe e la coda di messaggi sottostante, specificado il
nome della pipe, il massimo numero di messaggi bufferizzabili e la lunghezza massima di
28
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
ciascun messaggio.
Un task può essere bloccato su una pipe in seguito ai seguenti eventi:
• leggere da una pipe vuota finchè il dato non è disponibile
• scrivere in una pipe satura finchè non si libera nuovo spazio
Le pipe forniscono un importante servizio assente nelle code di messaggi: la possibilità di
usare la select(). Questa routine permette ad un task di attendere la disponibilità di dati su
un qualsiasi dispositivo I/O all’interno di un set, tra cui socket network e dispositivi
seriali.
Per utilizzare i
servizi
offerti
dalle pipe VxWorks
include il
componente
INCLUDE_PIPES.
4.3.5 Eventi VxWorks
Forniscono un mezzo di comunicazione e sincronizzazione tra task e: altri task, ISR,
semafori, code di messaggi.
Gli eventi vengono utilizzati poichè la loro gestione è leggera, infatti nessun oggetto viene
creato. Un task può gestire fino a 32 eventi, identificati da flag, tali flag sono memorizzati
in un registro eventi e sono codificati su 32 bit (i bit dal 25 al 32 sono riservati per Wind
River). Da notare che un flag evento di per se non ha alcun significato, ma lo acquista in
base a come è stato progettato il task che dovrebbe reagire a tale flag.
Gli eventi sono simili ai segnali, inviati ai task in maniera asincrona, ma a differenza dei
segnali la loro ricezione è sincrona e non richiede un gestore. Per poter usufruire dei
servizi concessi tramite gli eventi, VxWorks deve essere configurato con il componente
INCLUDE_VXEVENTS.
Un task può attendere uno o più eventi, o semplicemente controllarne la ricezione tramite
la chiamata eventReceive() bloccante. Possono essere ricevuti eventi da semafori o da
29
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
code di messaggi a patto che il task vi sia precedentemente registrato rispettivamente
tramite semEvStart() e msgQEvStart(); solo un task alla volta può essere registrato a un
semaforo o ad una coda di messaggi; inoltre un task può ricevere eventi da un altro task o
dall'ISR inviati tramite la eventSend().
Una vota che un task è registrato ad un semaforo, riceverà un evento da questo nel caso di
una chiamata semGive() e di assenza di task pendenti sul relativo semaforo.
Se invece il task è registrato presso una coda di messaggi, riceverà un evento nel caso sia
ricevuto un messaggio ma non ci sono task in attesa di questo.
Per fermare l'invio di eventi da parte di un semaforo o di una coda di messaggi si usano
rispettivamente le routine semEvStop() e msgQEvStop().
4.3.6 Segnali
Sono servizi del sistema operativo sviluppati per controllare eventi eccezionali e
alterazioni asincrone del flusso di controllo; risultano essere simili in molti aspetti alle
interruzioni hardware.
In accordo con POSIX, VxWorks utilizza 63 segnali, ognuno dei quali ha uno specifico
numero identificativo e un'azione predefinita, il valore 0 è riservato al segnale NULL.
I segnali possono essere mandati da task ad altri task o a processi, e posso essere ricevuti o
ignorati, ciò dipende dalla configurazione della maschera dei segnali del ricevente; alcuni
di essi tuttavia non possono essere ignorati come SIGKILL o SIGSTOP. Il loro invio
avviene mediante la routine sigqueue() che ammette bufferizzazione, mentre la ricezione
implica l’interruzione dell’esecuzione corrente del task e l’avvio del gestore segnali.
Per
utilizzare
i
servizi
dei
segnali
VxWorks
include
il
componente
INCLUDE_SIGEVENT.
30
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Capitolo 5
I/O system
Il sistema I/O di VxWorks è sviluppato per presentare una semplice e uniforme interfaccia
indipendente per ogni tipo di dispositivo, includendo:
• dispositivi orientati ai caratteri come terminali o righe di comunicazioni
• dispositivi a blocchi ad accesso casuale come dischi
• dispositivi virtuali come pipe e socket
• dispositivi di monitoraggio e controllo come dispositivi I/O digitali o analogici
• dispositivi network che consentono l’accesso a dispositivi remoti
Il sistema I/O di VxWorks fornisce librerie C standard sia per l’I/O base che per quello
bufferizzato, rispettivamente compatibili con UNIX e con ANCI C.
Per
usufruire
dei
servizi
dell’I/O
system
bisogna
includere
il
componente
INCLUDE_IO_SYSTEM.
Il seguente diagramma illustra le relazioni esistenti fra i diversi componenti del sistema
I/O disponibili per i processi real-time.
31
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Figura 5: Panoramica sul sistema I/O
In VxWorks l’accesso ai dispositivi di I/O avviene attraverso l’utilizzo di file, che possono
essere riferiti a:
• un dispositivo non strutturato come un canale di comunicazione seriale o una pipe
• un dispositivo ad accesso casuale strutturato contenente un file system
5.1 I/O base
È il livello più basso dell’I/O in VxWorks e la sua interfaccia è compatibile con le
primitive I/O nella libreria standard C. Ci sono sette routine I/O base: creat(), remove(),
open(), close(), read(), write(), ioctl().
Al livello I/O base i file sono identificati da un descrittore, valore intero restituito dalla
chiamata open() o creat() e utilizzato come parametro dalle altre routine.
I descrittori dei file non sono globali, ed il kernel, così come ogni RTP, ha il suo set; i task
all’interno del kernel o di uno specifico processo condividono i descrittori del file. Il
numero massimo di file descriptor che possono essere aperti simultaneamente in un
processo è specificato nella file descriptor table .
32
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Tre descrittori file hanno un particolare significato e sono:
• 0 usato per lo standard input (stdin)
• 1 usato per lo standard output (stdout)
• 2 usato per lo standard error output (stderr)
Questi sono usati per rendere indipendente l’applicazione dall’attuale assegnamento I/O.
5.2 I/O bufferizzato
La libreria buffered I/O è compatibile con la libreria stdio di UNIX e Windows e fornisce
il supporto completo ANSI C.
Nonostante il sistema I/O di VxWorks sia efficiente, le chiamate di basso livello generano
un seppur ridotto overhead. Per rendere tale sistema più efficiente la libreria stdio
implementa uno schema di buffering in cui i dati sono letti e scritti in grandi segmenti e
bufferizzati privatamente, tale bufferizzazione è trasparente all’applicazione essendo
automaticamente gestita dalle routine e dalle macro stdio.
Ad esempio per aprire un file con stdio si utilizza la routine fopen() invece di open(),
questa ritorna un puntatore associato con una struttura di tipo FILE contenente il file
descriptor per accedere ai dati del file corrispondente.
5.3 I/O asincrono
VxWorks consente di gestire le operazioni di input e output in maniera asincrona (AIO
Asynchronous Input/Output), disaccoppiandole dall'attività di particolari task quando sono
logicamente indipendenti.
Il beneficio che ne consegue è un'aumento dell'efficienza generale garantito dalla
possibilità di servire operazioni I/O esclusivamente quando tutte le risorse necessarie sono
disponibili, evitando, quindi, inutili blocchi.
Per includere il supporto AIO bisogna configurare VxWorks con il componente
INCLUDE_POSIX_AIO.
33
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Le principali routine POSIX AIO, presenti nella libreria aioPxLib, sono:
• aio_read(): crea un'operazione asincrona di lettura
• aio_write(): crea un'operazione asincrona di scrittura
• lio_listio(): crea una lista di massimo LIO_MAX richieste I/O asincrone
• aio_returned(): rileva lo stato di un'operazione AIO completata
• aio_suspended(): mette in attesa finché un'operazione di AIO è conclusa, interrotta o
scaduta
Ogni routine AIO, tra i suoi parametri, presenta un AIO control block (aiocb), il chiamante
deve specificare lo spazio riservato all'aiocb e questo deve rimanere disponibile durante
tutta l'operazione AIO. Ogni aiocb descrive una singola operazione.
34
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Capitolo 6
File system
VxWorks mette a disposizione una grande varietà di file system adattabili a differenti tipi
di applicazioni. Più file system posso essere presenti contemporaneamente su un singolo
sistema VxWorks, su più istanze. Un’istanza (vedi figura seguente) è quindi composta da
un file system, da un block device, e dall’XBD extended block device che fornisce servizi
per quello specifico blocco.
Figura 6: Istanza VxWorks
35
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
I file system usati per i dispositivi removibili fanno uso di un file system monitor,
utilizzabile includendo il componente INCLUDE_FS_MONITOR, per la rilevazione
automatica del dispositivo inserito e del relativo file system.
Illustriamo quali sono i principali file system utilizzabili in VxWorks:
• VRFS Virtual Root File System: un file system virtuale per l’uso di applicazioni che
richiedono file system POSIX. Si presenta come una semplice cartella nella quale gli altri
dispositivi e file system possono accedere. Per includere VRFS in VxWorks bisogna
configurare il kernel con il componente INCLUDE_VRFS.
• HRFS Highly Reliable File System: un file system transazionale sviluppato per sistemi
real-time: non viene mai a trovarsi in uno stato inconsistenete ed è rapido nel recupero in
caso di cali di alimentazione, organizza in maniera efficiente la gestione gerarchica dei file
e delle cartelle, ed è configurabile con politiche di commit. È necessario includere il
componente INCLUDE_HRFS.
• dosFs: un file system compatibile con MS-DOS, può essere usato su memorie flash. Le
principali caratteristiche sono: gestione gerarchica di file e cartelle, possibilità di scelta tra
allocazione contigua o non contigua dei file, capacità di avviare VxWorks da un file
system dosFs.
• rawFS: fornisce un semplice file system che tratta un intero disco come un singolo
grande file, ciò ottimizza l’occupazione di memoria e le performance se non sono richieste
funzioni complesse; tutte le operazioni di lettura e scrittura fanno riferimento ad indirizzi
composti dalla combinazione della prima locazione del disco e di un offset, espresso in
byte.
36
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
• cdromFS: permette alle applicazioni di leggere dati da CD-ROM formattati in accordo
con lo standard ISO 9660; per accedere a tali dati vengono usate le primitive POSIX I/O
standard.
• ROMFS Read-Only Memory File System: un semplice file system configurato in sola
lettura che memorizza file e cartelle in modo lineare e fornisce la possibilità di
raggruppare applicazioni VxWorks con il sistema operativo. È necessario includere il
componente INCLUDE_ROMFS.
• TSFS Target Server File System: progettato per fini di sviluppo e diagnostica, virtualizza
le caratteristiche del file system relativo al target supportando tutte le funzionalità di
VxWorks, in un ambiente completamente localizzato sulla macchina host; fornisce tutte le
caratteristiche I/O dei driver network per l’accesso remoto, senza richiedere alcuna risorsa
target, ad eccezione di quelle indispensabili per la comunicazione tra sistema target e host.
Bisogna includere il componente INCLUDE_WDB_TSFS.
37
Analisi del sistema operativo VxWorks per lo sviluppo di applicazioni real-time
Conclusione
Sono state descritte le caratteristiche salienti del sistema operativo VxWorks.
Quello che se ne può trarre, oltre a una mera conoscenza tecnica, e quello che può far
apprezzare VxWorks è la possibilità concessa al singolo programmatore di modificare ed
eventualmente aggiungere pezzi rilevanti di logica al sistema operativo.
Una prova di ciò è la possibilità di programmare un proprio schedulatore, oppure
modificare la logica generale di scheduling, ad esempio, sostituendo l'algoritmo
Round-Robin del sistema (il quale genera comunque overhead a causa dei continui cambi
di contesto) con un algoritmo di tipo cooperativo più ancestrale (lo aveva la famiglia dei
Windows 3.x, ad esempio, prima che subentrasse Windows NT) in cui è l’applicativo
stesso che cede spontaneamente la CPU per favorire il completamento di tutti i task
facendolo, però, il minor numero di volte e solo quando serve.
La possibilità di intervenire sui meccanismi del codice di sistema non è cosa molto ben
vista, ai nostri giorni, da parte dei produttori di sistemi operativi proprietari.
L'opportunità che offre in quest'ambito un prodotto come VwWorks lo rende, in qualche
modo, più vicino ai sistemi aperti e ciò offre un'apprezzabile chance al singolo
sviluppatore di esprimere le proprie capacità creative.
38
Bibliografia
[1]
Wind River Systems, Inc. 2008. “VxWorks Application Programmer’s Guide, 6.7”
[2]
Wind River Systems, Inc. 2007. “VxWorks Kernel Programmer’s Guide, 6.6”
[3]
Wind River Systems, Inc. 2008. “VxWorks BSP Developer’s Guide, 6.7”
[4]
Wind River Systems, Inc. 2006. “VxWorks Workbench User’s Guide, 2.5”
[5]
Wind River Systems, Inc. 2005. “VxWorks Simulator User’s Guide, 6.1”
[6]
Wind River Systems, Inc. “www.windriver.com”
[7]
Mario Malcangi. 2011. “Sistemi embedded e sistemi operative real-time”
[8]
Rafael V.Aroca, Glauco Caurin. “A Real Time Operating Systems (RTOS)
Comparison”
[9]
Jim Collier. 2004. “An Overview Tutorial of VxWorks Real-Time Operating
System”
[10] Colin Walls. 2010. “AMP vs SMP”
[11] IEEE Computer Society. 2004. “1003.13 IEEE Standard for Information
Technology - Standardized Application Environment Profile (AEP) - POSIX Realtime and
Embedded Application Support”
39