Scuola Politecnica e delle Scienze di Base Corso di Laurea in Ingegneria Informatica Elaborato finale in Sistemi Real Time Analisi del Sistema Operativo RTEMS per lo sviluppo di applicazioni Real Time Anno Accademico 2013/2014 Candidato: Emanuele Capone matr. N46001016 Alla mia famiglia, per avermi dato un’enorme possibilità. Indice Indice .................................................................................................................................................. III Introduzione ......................................................................................................................................... 4 Capitolo 1: Architettura Interna ........................................................................................................... 6 1.1 Classificazione Resources Manager........................................................................................... 7 Capitolo 2: Scheduler ......................................................................................................................... 12 2.1 Deterministic Priority Scheduler .............................................................................................. 13 2.2 Simple Priority Scheduler ........................................................................................................ 14 2.3 Simple SMP Priority Scheduler ............................................................................................... 14 2.4 Earliest Deadline First Scheduler ............................................................................................. 15 2.5 Constant Bandwidth Server Scheduler .................................................................................... 16 Capitolo 3: Ciclo di vita dei task ........................................................................................................ 19 3.1 Condizioni di blocco/sblocco di un task .................................................................................. 21 Capitolo 4: RTEMS in ambiti applicativi .......................................................................................... 24 4.1 Solar Dynamic Observatory ..................................................................................................... 24 4.2 Electra ...................................................................................................................................... 26 Conclusioni ........................................................................................................................................ 27 Bibliografia ........................................................................................................................................ 28 Introduzione RTEMS, acronimo di Real-Time Executive for Multiprocessor Systems, è un sistema operativo Real-Time distribuito in modalità Open Source e attualmente gestito dalla OAR corporation in collaborazione con la comunità di sviluppatori che lo supportano. RTEMS è stato progettato per sistemi embedded, ma nel corso dei suoi undici anni di vita ha trovato un utilizzo pratico in numerosi progetti e applicazioni mission critical in ambito industriale, medico, spaziale e su una vasta gamma di architetture hardware come ARM, Intel, MIPS, PowerPC e molte altre. Una delle particolarità di questo sistema operativo è il supporto a diversi standard quali POSIX e ITRON, oltre alla compatibilità con numerose Application Program Interface di tipo open. Tra le principali caratteristiche di funzionamento di RTEMS c’è di sicuro il supporto al multitasking, al multiprocessore (così come suggerisce l’acronimo), la possibilità di avere a nostra disposizione scheduling priority-based e preemptive, il supporto all’allocazione dinamica della memoria, la presenza di un rate monotonic scheduling e molto altro che analizzeremo nel corso dell’elaborato. In linea generale, RTEMS, essendo un sistema operativo real-time deve soddisfare dei vincoli temporali ben precisi: in sintesi possiamo dire che la correttezza di funzionamento in questo caso dipende non solo dalla validità dei risultati prodotti, ma anche dal tempo in cui essi vengono restituiti, da qui si arriva a parlare di sistemi dal doppio concetto di correttezza, sia logico che temporale. Il termine “Real” invece sta a indicare che la risposta di un sistema Real-Time a eventi esterni ad esso deve avvenire durante l’evolversi degli eventi stessi, quindi il tempo interno del sistema e quello dell’ambiente in cui opera 4 dovranno necessariamente essere misurati con lo stesso riferimento. Uno dei punti cardini sui quali si basa la filosofia di sviluppo di RTEMS è l’essere quasi del tutto Open Source. Il codice sorgente, infatti, è costituito da una collezione di software con licenze di tipo free, che possono essere utilizzati liberamente da sviluppatori di software proprietari senza richiedere particolari vincoli di licenza sull’applicativo finale. In altre parole chiunque può modificare ed eventualmente ridistribuire il codice di RTEMS rispettando i termini della General Public License (GPL modified) pubblicata dalla Free Software Foundation, ma eventualmente con la possibilità di includere particolari header o templates per la produzione di un eseguibile che non verrà distribuito con licenza GPL, ma ad esempio con licenza proprietaria. Tuttavia come spesso accade con i software Open Source, anche RTEMS è distribuito con la speranza di essere utile ai fini di un progetto che lo richiede, ma senza alcun tipo di garanzia sul suo corretto funzionamento in seguito a modifiche o addirittura utilizzato in accoppiata con determinati tipi di software. Ovviamente il tipo di distribuzione Open Source ha permesso a numerosi progetti, sia indipendenti che sovvenzionati da grandi aziende, di usufruire dei servizi di questo importante sistema Real Time, contribuendo alla crescita di RTEMS insieme alla stessa OAR Corporation (On-Line Applications Research), in questo momento a capo della gestione del progetto. Durante l’elaborato saranno presi in considerazione i principali aspetti di questo sistema operativo, soffermandosi dapprima sull’architettura interna del sistema, per poi passare a un’analisi approfondita del comportamento dei processi, con il ciclo di vita dei task e gli scheduler utilizzati per la gestione degli stessi, chiudendo infine con una breve disamina degli ambiti applicativi in cui RTEMS è utilizzato, fornendo alcuni esempi interessanti di progetti pratici in via di sviluppo o abbastanza recenti. 5 Capitolo 1: Architettura interna Prima di partire con l’analisi del funzionamento vero e proprio di questo sistema e la gestione dei task real-time, è interessante andare ad osservare il modo in cui è stato concepito RTEMS, vale a dire la sua architettura interna e il modo in cui i vari componenti collaborano tra loro per fornire funzionalità agli sviluppatori di applicazioni e progetti. Volendo studiare l’architettura dell’OS come un qualsiasi sistema General Purpose, vale a dire sotto forma di strati sovrapposti, anche RTEMS può essere rappresentato come una sorta di strato software intermedio tra il livello hardware e quello applicativo. Chiaramente viene fornita un’interfaccia del kernel al livello applicativo formata dalle cosiddette “RTEMS API Calls”, raggruppate a loro volta in moduli chiamati resource managers, ciascuno dei quali è responsabile della fornitura di servizi specifici per il funzionamento generale del sistema. Il tutto è coordinato da un nucleo centrale chiamato RTEMS Core che comprende le varie routine necessarie per interfacciarsi con la CPU, e risulta di fatto il maggior responsabile della gestione del sistema a basso livello e dei drivers dei dispositivi, tutti i vari manager chiaramente non potrebbero funzionare correttamente senza la presenza di questo nucleo coordinatore. Da un punto di vista concettuale (così com’è ben visibile in Figura 1) potremmo vedere la struttura di RTEMS come una torta il cui centro è caratterizzato dal nucleo del sistema, ciascuna fetta è un modulo che è possibile richiamare a livello applicativo attraverso le API messe a disposizione. 6 1.1 Classificazione Resources Manager All’interno di questo paragrafo è presente una breve disamina per i vari manager che supportano il sistema operativo, i quali vengono raggruppati per tipologia e scopi funzionali, ciascuno con le proprie caratteristiche e le direttive utilizzabili per la fruizione di determinati servizi. Ogni manager è fondamentale per RTEMS, tuttavia è stata posta particolare attenzione nei confronti di alcune componenti come il Semaphore Manager o il Rate Monotonic Manager, che hanno compiti più onerosi. Figura 1: Struttura Managers Manager che si occupano delle politiche di gestione e temporali dei task - L’Initialization Manager è il responsabile dell’avvio e lo spegnimento di RTEMS, più precisamente si occupa della creazione e l’avvio dei task d’inizializzazione e invoca le varie routine per l’inizializzazione dei driver di periferica. In caso di sistemi multiprocessore il manager si occupa di inizializzare anche l’interprocessor communication layer. - Il Task Manager raggruppa una serie di direttive per amministrare, creare ed eventualmente eliminare task come ad esempio rtems_task_create (crea un task), 7 rtems_task_start (avvia un task) e rtems_task_set_priority (imposta la priorità di un task). - L’Interrupt Manager, invece, si occupa di fornire meccanismi di risposta a interrupt generate esternamente, in maniera tale da soddisfare i vincoli temporali dell’applicazione. Il manager in questione permette tempi di risposta alle interrupt molto rapidi, alterando la normale esecuzione e facendo in modo che un task sia prelazionato all’uscita di un processo da un ISR (Interrupt Service Routine). - Tra i manager dedicati alla gestione delle politiche temporali, c’è il Timer Manager, il quale non fa altro che fornire supporto per le funzionalità di temporizzazione più generiche, con direttive quali rtems_timer_create (Crea un timer), rtems_timer_delete (elimina un timer esistente) e molte altre. - Il Clock Manager si occupa sempre di funzionalità legate alla gestione temporale, ma in maniera più specifica, attraverso direttive del tipo rtems_clock_set (per importare data e ora), rtems_clock_get_uptime (restituisce il tempo trascorso dall’avvio) e molte altre. - Infine fa parte di questa categoria il Fatal Error Manager, un elemento fondamentale che riesce a gestire gli errori fatali o irrecuperabili, oppure semplicemente le classiche terminazioni di sistema. Manager che si occupano di sincronizzare gli eventi tra i vari task - Il Semaphore Manager è un componente imprescindibile del sistema, giacché fornisce i meccanismi basati sull’algoritmo di Dijkstra per l’implementazione di semafori e conseguente supporto alla sincronizzazione e mutua esclusione dei processi in esecuzione. Mette a disposizione, quindi, tutte le direttive necessarie per la creazione, la rimozione e il rilascio dei semafori. Grazie a questo manager, infatti, viene implementato il meccanismo di Priority Inheritance per risolvere il problema di inversione di priorità, assegnando al task 8 che detiene una risorsa la priorità più alta tra i processi in attesa dello sblocco di quella stessa risorsa, in questo modo non c’è il rischio che un task a priorità intermedia possa eseguire prima del processo a priorità più alta che è stato precedentemente bloccato. In realtà RTEMS implementa anche Priority Ceiling, un altro protocollo capace di risolvere lo stesso problema ma in maniera differente, introducendo un ceiling per ogni risorsa protetta, definito come la massima tra le priorità dei task che potrebbero usare e conseguentemente bloccarsi su quella determinata risorsa; a questo punto un processo potrà eseguire se e solo se la sua priorità è strettamente maggiore del massimo tra i ceiling delle risorse attualmente occupate. - Il Message Manager, invece, si occupa di gestire la comunicazione tra i vari processi e la necessaria sincronizzazione mediante l’uso di code di messaggi in RTEMS. Le direttive utilizzate in questo caso sono del tipo rtems_message_queue_create/delete/broadcast (rispettivamente per creare, eliminare una coda, oppure per inviare un messaggio in broadcast) con l’ultimo termine che cambia in base alla funzione voluta. - L’Event Manager è quel gestore capace di fornire un metodo a elevate prestazioni per la sincronizzazione e la comunicazione tra task all’interno del sistema. In questo caso le direttive utilizzate sono solamente due, rtems_event_send e rtems_event_receive. - Chiudendo con l’analisi sui gestori dedicati alla sincronizzazione, bisogna citare il Signal Manager, elemento che fornisce le funzioni necessarie per la comunicazione asincrona tra task, che si basa come ben sappiamo sull’invio di un messaggio o un semplice segnale senza attendere risposta, continuando l’esecuzione. Anche in questo caso le direttive utilizzabili sono solamente due, rtems_signal_catch (per stabilire un ASR) e rtems_signal_send (per inviare un segnale ad un task). 9 Manager responsabili della gestione della memoria - Il Partition Manager fornisce tutto il necessario per riuscire ad allocare dinamicamente la memoria a disposizione in unità dalle dimensioni prefissate. Le direttive utilizzabili sono del tipo rtems_partition_create/ident/delete etc. con l’ultima parola che varia in base alla funzione richiesta. - Il Region Manager invece ha una funzione abbastanza simile al Partition Manager, in questo caso però il gestore fornisce ancora funzioni per allocare dinamicamente la memoria, questa volta però in unità di dimensione variabile. Alle direttive di Partition Manager basta sostituire “partition” con “region” per il resto sono abbastanza simili in quanto a funzionalità. - Il Dual Ported Memory Manager: fornisce i meccanismi necessari per convertire gli indirizzi tra rappresentazione interna ed esterna per aree di memoria Dual-Ported multiple. Tra le direttive utilizzabili troviamo rtems_port_create, rtems_port_delete e soprattutto rtems_port_external_to_internal/internal_to_external. Manager che implementano le altre funzionalità necessarie - L’I/O Manager fornisce un particolare meccanismo per l’accesso ai driver dei dispositivi e una metodologia per organizzare gli stessi driver. Tra le direttive utilizzabili ci sono rtems_io_initialize (per inizializzare un driver), rtems_io_open/close (per aprire o chiudere la connessione con un dispositivo di I/O) e rtems_io_read/write (per scrivere o leggere da un dispositivo). - Il Rate Monotonic Manager ha un’importanza cruciale per il funzionamento del sistema, il tutto sarà chiarito all’interno del capitolo dedicato agli scheduler, ma in linea generale 10 possiamo dire che si occupa di implementare l’omonimo algoritmo per la schedulazione di task periodici. Permette inoltre di avere informazioni riguardo l’esecuzione di questi periodi, restituendo statistiche che possono risultare utili all’utente per la sua applicazione. Anche in questo caso ovviamente abbiamo numerose direttive per la gestione dei periodi e delle statistiche. - L’User Extensions Manager si occupa di fornire gli strumenti adatti per permettere allo sviluppatore di un’applicazione di estendere il suo software, dandogli la possibilità di utilizzare routine aggiuntive invocate in corrispondenza di eventi critici di sistema. - Il Multiprocessing Manager fornisce, infine, tutto il necessario per la gestione di RTEMS con sistemi multiprocessore. Il manager è stato introdotto per aumentare l’efficienza del sistema operativo, poiché grazie ad esso, su piattaforme aventi diversi processori, è possibile condividere dati e risorse globali tra le diverse CPU, aumentando però la complessità della gestione generale del sistema, in quanto parliamo pur sempre di un sistema real-time. 11 Capitolo 2: Scheduler Gli scheduler sono una parte fondamentale di un qualsiasi sistema operativo, giacché il loro compito è scegliere quali processi mandare in esecuzione tra quelli presenti nella coda dei processi pronti, utilizzando opportuni algoritmi in base alle esigenze e alle condizioni del sistema in esecuzione. Com’è facile intuire, essi assumono un’importanza ancora maggiore nell’ambito dei sistemi real-time, poiché devono riuscire a gestire ed organizzare l’esecuzione dei vari task in modo tale da assicurare che ognuno di essi termini entro la propria deadline, quindi anche in questo caso il tutto ruota attorno ai requisiti temporali di ogni processo. La deadline non è altro che il tempo massimo entro cui un processo realtime deve terminare la propria esecuzione, spesso, infatti, la violazione di questo fattore può portare ad eventi catastrofici se abbiamo a che fare con task hard real-time, altrimenti con processi di tipo soft può essere causa di un degrado delle prestazioni. Dalla versione 4.10 RTEMS prevede cinque tipi diversi di scheduler priority based, chiamati in questo modo poiché assicurano che il task in esecuzione in qualsiasi momento è sempre quello a priorità più alta, ovviamente tra quelli presenti nella coda dei processi pronti. La possibilità di supportare diversi algoritmi, inoltre, la cui implementazione risiede all’interno dell’RTEMSCore, è data da un plugin framework previsto in RTEMS: l’utente in questo modo può decidere quale tipo di scheduling utilizzare tra quelli presenti, in base alle proprie esigenze di sviluppo, oppure implementarne uno proprio e configurarlo con il sistema. Se non ci sono configurazioni da parte dell’utente, di default RTEMS per i sistemi single core fa uso di Deterministic Priority Scheduler, algoritmo presente fin dalla prima versione del sistema operativo e l’unico utilizzabile fino alla versione 4.10. Ad esso 12 si sono poi aggiunte le variazioni conosciute come SPS e SSMP e due algoritmi particolarmente famosi utilizzati in molti altri sistemi real-time sui quali sono presenti alcuni approfondimenti, vale a dire EDF e CBS. Una volta che lo scheduling utilizzato decide quale task mandare in esecuzione entra in atto il dispatcher, elemento presente anche in RTEMS e responsabile dell’assegnazione della CPU ad un particolare task pronto, in altre parole è colui che si occupa fisicamente di mandare in esecuzione un processo. Per assegnare un task al processore, però, c’è bisogno di un’operazione di context switching, durante la quale il dispatcher si occupa di salvare lo stato attuale del processo e ripristinare lo stato del task da mandare in esecuzione e salvato in precedenza, operazione che in realtà avviene in qualsiasi altro sistema operativo. Tutte queste informazioni utili al context switching e di conseguenza all’esecuzione di un task, sono conservate nel cosiddetto Thread Control Block (TCB). Di seguito è presente una disamina per ogni algoritmo di scheduling previsto dal sistema, ponendo particolare attenzione soprattutto agli algoritmi di EDF e CBS, che risultano leggermente più complessi per quanto riguarda il comportamento generale e il modo in cui vengono implementati. 2.1 Deterministic Priority Scheduler (DPS) DPS, come già specificato in fase d’introduzione, è l’unico algoritmo di scheduling presente da sempre in RTEMS a partire dalla prima versione del sistema, ed è di tipo preemptive, vale a dire ha la possibilità di interrompere temporaneamente un processo in qualsiasi momento in favore di un altro a priorità più alta, per poi riattivarlo una volta che il task prioritario ha terminato la sua esecuzione. L’implementazione di quest’algoritmo prevede l’utilizzo di un array di code FIFO, ciascuna con una sua priorità; scelta la coda da servire, i task saranno mandati in esecuzione con politica First In First Out, quindi il primo processo ad essere servito sarà quello che è arrivato prima degli altri. Le code presenti sono 256, una per ogni livello di priorità, in questo modo l’algoritmo in questione costa solo tre Kilobytes di memoria RAM al sistema, un utilizzo davvero esiguo in termini 13 di risorse hardware. Per utilizzare questo scheduling la direttiva di pre-compilazione da inserire nel codice sorgente del programma sviluppato è CONFIGURE_SCHEDULER_PRIORITY e fa uso di un solo core, quindi non è perfettamente ottimizzato per sistemi multiprocessore. 2.2 Simple Priority Scheduler (SPS) Il funzionamento di SPS è molto simile a DPS, anzi a dire il vero il modo in cui agisce è perfettamente identico, cambia però l’implementazione reale dell’algoritmo. Questa volta a essere utilizzata è una singola struttura dati, una lista linkata utile a gestire tutti i task nella coda dei processi pronti, tutto ciò però a discapito della complessità: la struttura dell’implementazione prevede, infatti, che venga eseguita una ricerca lineare sui task ready per decidere quale mandare in esecuzione, chiaramente in base alle priorità assegnate. Facendo un veloce confronto con DPS, il Simple Priority Scheduler è ancor più parsimonioso in termini di risorse utilizzate, tuttavia prevede una maggiore complessità nell’algoritmo di selezione dei task calcolata come O(n), con n numero di task pronti, dovuta alla già citata ricerca lineare. Possiamo concludere dicendo che SPS è una buona soluzione da adottare in RTEMS solo se viene utilizzato in piccoli sistemi con un numero di task da gestire abbastanza esiguo, in questo caso la complessità è trascurabile ma abbiamo un buon guadagno in termini di impiego delle risorse. Nel caso in cui si voglia utilizzare questo scheduling, la direttiva di pre-compilazione da specificare è CONFIGURE_SCHEDULER_SIMPLE, anche in questo caso l’algoritmo non è ottimizzato per sistemi multi-core. 2.3 Simple SMP Priority Schedule (SSMP) Parlando di DPS e SPS, abbiamo già sottolineato che si tratta di due soluzioni utilizzabili in sistemi single core, mentre per quanto riguarda le architetture multiprocessore risultano decisamente poco efficienti. SSMP non è altro che l’adattamento di Simple Priority Scheduler a sistemi dotati di più core della CPU che lavorano nello stesso momento. La particolarità di quest’algoritmo consiste nel riuscire a schedulare threads differenti tra i 14 diversi core di un’architettura symmetric multiprocessor (SMP), inoltre fornisce anche una soluzione nel momento in cui bisogna prelazionare uno fra diversi threads aventi la stessa priorità: l’algoritmo in questo caso non fa altro che sospendere il thread che ha eseguito per più tempo tra quelli prelazionabili. Per quanto riguarda quest’algoritmo, la direttiva pre-compilativa da specificare è CONFIGURE_SCHEDULER_SIMPLE_SMP. 2.4 Earliest Deadline First (EDF) Un algoritmo di scheduling alternativo a DPS e SPS, per quanto riguarda le applicazioni single core, è il famoso EDF. Così come suggerisce l’acronimo, Earliest Deadline First manda in esecuzione tra i processi pronti quello con la deadline più vicina, o per meglio dire deadline assoluta più breve, in maniera tale da unificare il concetto di priorità e deadline stesso, seppur in maniera inversamente proporzionale. Le deadline vengono calcolate a loro volta con il Rate Monotonic manager, di cui si è già parlato nel capitolo precedente, che le fa coincidere con il periodo dei task, dopodiché tutti i processi sono inseriti all’interno di un’unica coda ready implementata come un albero Red-Black. Bisogna tuttavia porre l’accento su un aspetto fondamentale di EDF utilizzato in RTEMS, i task all’interno del sistema hanno due tipi di priorità differenti, descrivibili in questo modo: se un processo ha una deadline che è stata fissata utilizzando il Rate Monotonic Manager allora la deadline stessa coincide con la priorità e il task è detto priority-driven; nel caso in cui invece il task non ha una deadline specificata, oppure quella precedentemente fissata è stata cancellata, allora viene definito processo di background, e la priorità è quella assegnata durante l’inizializzazione. A questo punto per quanto riguarda la schedulazione vera e propria, vengono mandati in esecuzione dapprima tutti i task priority-driven, dopodiché si passa a quelli di background in base alle priorità iniziali. Si intuisce quindi che a causa dell’utilizzo dell’algoritmo EDF con l’esecuzione di task periodici, il Rate Monotonic Manager è di importanza fondamentale, per questo motivo vengono messe a disposizione alcune direttive come rtems_rate_monotonic_period per dichiarare le varie deadline, oltre a rtems_rate_monotonic_cancel e rtems_rate_monotonic_delete per cancellare la deadline precedentemente assegnata ad un 15 task. Non bisogna dimenticare, infine, che tra i vantaggi offerti da EDF uno dei più importanti è quello di sfruttare un’altissima quantità di CPU, teoricamente il 100%, con una complessità dell’algoritmo pari a O(log(n)) dovuta alla ricerca all’interno dell’albero Red-Black, dove n è il numero di task presenti nella coda ready del sistema. Anche in questo caso nel codice sorgente dell’applicazione bisogna dichiarare l’utilizzo di EDF, attraverso la direttiva CONFIGURE_SCHEDULER_EDF. 2.5 Constant Bandwidth Server Scheduler (CBS) CBS è un’estensione di EDF, o meglio la differenza tra i due algoritmi è la presenza di un Server in CBS particolarmente utile soprattutto quando abbiamo la presenza contemporanea nel sistema di task periodici e aperiodici: il problema cardine è garantire l’esecuzione dei task periodici (di tipo hard real-time) senza ritardare eccessivamente quelli aperiodici. Tra le sue caratteristiche principali c’è di sicuro quella di assicurare un isolamento temporale dei task: in parole povere le esecuzioni dei vari processi non si influenzano a vicenda, ma viceversa si comportano come se ogni task avesse a disposizione un processore dedicato e indipendente dagli altri. Il Constant Bandwidth Server prevede anche un meccanismo di protezione utile ad assicurare che la banda allocata al server non sia superata, indipendentemente dalle richieste di calcolo dei task. Analizzando il modo in cui viene implementato il tutto in maniera pratica, è chiaro che ciascun task è assegnato ad un server, caratterizzato da un periodo e una capacità che indica il massimo budget consumabile all’interno del periodo stesso, mentre la banda del server non è altro che il rapporto tra questi due valori (capacità/periodo): concretamente essa può essere definita come la frazione di CPU riservata dallo scheduler per ogni periodo successivo; definito Ts il periodo e Qs il budget, la banda allocata al server sarà Us = Qs / Ts. Oltre a questi fattori, in ogni istante lo stato del server può essere rappresentato con altri due valori: - Cs: budget o capacità del server all’istante t, inizialmente è uguale 0 ma può assumere al massimo un valore pari a Qs. 16 - Ds: deadline corrente assegnata a un task, anch’essa inizialmente è 0, può essere spostata di un particolare valore e in corrispondenza di particolari eventi come descritto in seguito. Tenendo ben presenti i fattori e simboli fino ad ora descritti, a questo punto è possibile analizzare le regole alla base del funzionamento di CBS, sintetizzabili in quattro punti fondamentali, ciascuna per ogni condizione di funzionamento: 1. Se arriva una nuova richiesta quando quella attuale è attiva, la nuova viene inserita all’interno di una coda gestita tipicamente con politica FIFO (First In First Out). 2. Ipotizzando l’arrivo di una nuova richiesta all’istante t, nel momento in cui il server è idle (nessuna richiesta in esecuzione) possiamo avere due condizioni con le relative conseguenze, valutando la disuguaglianza 0 < Cs ≤ (Ds - t)*Us: se Cs (il budget attuale del server) è compreso tra quei due valori, allora la richiesta viene servita con i valori attuali del server, altrimenti se la disuguaglianza non è soddisfatta, si pone Cs = Qs (budget attuale uguale alla capacità originaria) e Ds = t + Ts (la deadline della richiesta viene traslata di una quantità pari al periodo del server). 3. Quando la richiesta corrente viene completata, il server si occupa di quella successiva, qualora fosse presente all’interno della coda, utilizzando eventualmente i valori attuali. 4. Quando invece il budget del server si annulla (Cs = 0) viene riportato nuovamente al valore massimo, vale a dire Qs, mentre la deadline viene ritardata di un periodo Ds = Ds + Ts. Quest’ultima regola è in realtà un meccanismo di protezione temporale che rende il tutto molto affidabile, ma è causa di prestazioni non proprio elevatissime di CBS rispetto ad 17 altri algoritmi di scheduling. Constant Bandwidth Server, inoltre, offre delle proprie API che permettono alle applicazioni di fissare la deadline in maniera diretta, senza l’utilizzo della direttiva rtems_rate_monotonic_period e di conseguenza del Rate Monotonic Manager, come avviene invece per EDF. Tra le altre direttive più importanti utilizzabili troviamo rtems_cbs_initialize per l’inizializzazione del server, rtems_cbs_set_parameters per impostare i parametri, rtems_cbs_get_server_id per ottenere l’id del server in uso e molte altre. In fase di pre-compilazione del codice sorgente dell’applicazione, invece, la direttiva da usare è CONFIGURE_SCHEDULER_CBS. 18 Capitolo 3: Ciclo di vita dei task Un task in RTEMS durante la schedulazione può trovarsi in cinque stati differenti, in base alle condizioni durante il suo ciclo di vita: executing, ready, blocked (o waiting), dormant e non-existent (o terminated). La struttura e il collegamento tra i vari stati sono ben visibili all’interno del grafo in figura 2, tuttavia è importante andare ad analizzare ciascuno stato o transizione e le condizioni sotto le quali avvengono cambiamenti. Un task è nello stato non-existent fino a quando è richiamata la direttiva rtems_task_create, mentre subisce una transizione da qualsiasi altro stato a quello di non-existent con la chiamata della direttiva rtems_task_delete. Un task presente in questo stato non ha un ID o un TCB assegnato e da qui deriva la sua denominazione, giacché il task in questione è come se non esistesse per gli altri processi del sistema, in pratica non può essere richiamato in alcun modo. Quando un task si trova nello stato di non-existent e viene richiamata la direttiva create, una transizione lo fa arrivare nello stato dormant dove di fatto risulta dormiente ma non ancora attivo, di conseguenza non potendo utilizzare risorse di sistema permane in questa condizione fino a quando viene richiamata la direttiva rtems_task_start, a quel punto lo troveremo nella coda dei processi pronti dove potrà essere schedulato dal processore e grazie al dispatching entrare nello stato di executing. Durante la sua esecuzione un task può bloccarsi poiché ad esempio è in attesa di un mutex, oppure può essere bloccato da un altro task presente nel sistema sotto dovute condizioni: nel primo caso il processo ha la facoltà di utilizzare alcune direttive come ad esempio rtems_task_wake_after o rtems_task_wake_when, nel secondo caso invece l’unica direttiva utilizzabile è rtems_task_suspend; nel prossimo paragrafo verranno descritte in maniera più precisa tutte le condizioni verificabili e le loro conseguenze nella transizione che porta un task a 19 bloccarsi o a tornare nella coda dei processi pronti. Figura 2: Grafo delle transizioni Per quanto riguarda invece la modalità di esecuzione vera e propria di un processo in RTEMS, essa può essere espressa con quattro elementi fondamentali o campi: • Preemption: indica la possibilità di un task di essere prelazionato o meno. • Timeslicing: è utilizzato per l’assegnazione della CPU a diversi processi aventi la stessa priorità. Più precisamente se il campo suddetto è abilitato, il sistema va a limitare il tempo massimo di esecuzione di un task prima ancora che un altro task di eguale priorità venga schedulato dalla CPU, regolando le operazioni di context switching dei task ugualmente prioritari. • ASP: acronimo di Asynchronous Signal Processing, se è abilitato, indica che i segnali ricevuti dal task saranno gestiti durante la prossima esecuzione del processo stesso. Viceversa, se l’opzione è disabilitata i segnali ricevuti rimangono in attesa fino a quando ASP non viene riabilitato. • Interrupt: il campo seguente indica invece quale livello delle interruzioni è abilitato durante l’esecuzione del task, ricordando che RTEMS supporta 256 livelli diversi di interrupt. 20 Queste componenti vengono usate, quindi, per modificare il processo di scheduling e alterare l’esecuzione di un task, il tipo di dato utilizzato per gestire la modalità di esecuzione dei task è rtems_task_mode. Riprendendo invece la disamina fatta per le caratteristiche di ciascun task, ognuno di essi può avere degli attributi, descrivibili in questo modo: • RTEMS_NO_FLOATING_POINT: il processo non usa il coprocessore numerico. • RTEMS_FLOATING_POINT: il processo utilizza il coprocessore numerico (occupa maggiore memoria). • RTEMS_LOCAL: c’è un’area privata per variabili non condivisibili con altri task (occupa maggiore memoria). • RTEMS_GLOBAL: le variabili utilizzate dal task sono globali. Il fatto che i task local e floating point occupino maggiore memoria, è dovuto alla necessità di memorizzare informazioni riguardo lo stato delle variabili di tipo privato o della floating point unit. Infine per terminare il discorso riguardo la gestione dei task in RTEMS e il relativo ciclo di vita con le transizioni corrispondenti, è necessario dare uno sguardo alle primitive utilizzabili, tutto ciò nell’approfondimento che segue dove, come già descritto in precedenza, ci si soffermerà sullo blocco e sblocco dei task. 3.1 Condizioni di blocco/sblocco di un task Durante il capitolo seguente sono state prese in considerazione le varie transizioni che portano un task a passare da uno stato all’altro, ora l’attenzione sarà posta sulle condizioni che devono essere verificate affinché un processo passi dallo stato blocked a quello ready e viceversa, considerando anche i passaggi da e verso lo stato di executing. 21 Un task qualsiasi può entrare nello stato di blocking se è verificata una di queste sette condizioni, ciascuna associata a una direttiva utilizzata, alcune delle quali già nominate in precedenza: • Un task richiama la direttiva rtems_task_suspend che blocca esso stesso o un altro processo del sistema; • Il task in esecuzione richiama la direttiva rtems_message_queue_receive con la condizione d’attesa e la coda dei messaggi vuota. • Il processo che sta eseguendo richiama la direttiva rtems_task_wake_after, con la quale si blocca per un certo periodo di tempo specificato durante la chiamata stessa. Se il campo corrispondente all’intervallo da definire è zero, il task torna subito nello stato ready. • Utilizzando la direttiva rtems_task_wake_when, il processo si blocca fino a quando non viene raggiunto l’istante di tempo indicato, in corrispondenza del quale il task viene risvegliato come vedremo nelle condizioni di sblocco. • Un processo può richiamare la direttiva rtems_region_get_segment con una condizione d’attesa, poiché non c’è un segmento di memoria abbastanza ampio da soddisfare la richiesta del task. • Un task in esecuzione con la direttiva rtems_semaphore_obtain si blocca con una condizione di wait e il semaforo voluto non disponibile. • Il processo in esecuzione con la direttiva rtems_event_receive si blocca sempre con una condizione di attesa, poiché in questo caso gli eventi in corso in quel momento nel sistema non soddisfano la richiesta. • La direttiva rtems_rate_monotonic_period indica che il task corrente deve attendere uno specifico periodo rate monotonic per terminare l’esecuzione. Un processo in RTEMS, d’altro canto, può rientrare nello stato ready se è verificata una di queste altre sette condizioni differenti, ancora una volta associate a direttive: • Un task in esecuzione può richiamare rtems_task_resume con la quale riattivare un processo 22 sospeso che non è in attesa di alcuna risorsa dal sistema. • Un task mentre esegue può richiamare le direttive rtems_message_queue_send, rtems_message_queue_broadcast o rtems_message_queue_urgent che inseriscono un messaggio nella coda sulla quale il processo bloccato è in attesa, in maniera tale da farlo tornare nello stato di ready, pronto per essere schedulato. • Un processo con la direttiva rtems_semaphore_release può, invece, rilasciare un semaforo sul quale c’è un task bloccato in attesa. • Attraverso la direttiva rtems_event_send, un task può inviare una “event_condition” ad un altro processo bloccato in attesa di quella stessa condition. • Un processo può sbloccarsi se è terminato l’intervallo di tempo specificato nella direttiva rtems_task_wak_after utilizzata per eseguire la transizione verso lo stato di blocked. • Un task che ha in precedenza richiamato la direttiva rtems_task_wake_when, viene sbloccato e torna nello stato di ready se arriva quell’istante specificato nella direttiva. • Un task richiama la direttiva rtems_region_return_segment quando il segmento di memoria sul quale era bloccato il processo diventa disponibile ed è abbastanza ampio da contenerlo. • Dopo aver utilizzato la direttiva rtems_rate_monotonic_period per la transizione nello stato di blocked, un task torna nella coda dei processi pronti quando vede terminare il periodo specificato nella direttiva stessa. • Un processo nello stato blocked può sbloccarsi anche utilizzando semplicemente rtems_task_restart in maniera diretta. • Se un intervallo di timeout termina con un task che era bloccato su un evento particolare, un messaggio, un segmento o un semaforo, torna ad essere ready e si sblocca. • Se un altro processo utilizza una direttiva per eliminare una coda di messaggi, un semaforo o una regione di memoria su cui era bloccato un altro task, quel task torna nella coda dei processi ready. 23 Capitolo 4: RTEMS in ambiti applicativi Così come specificato durante l’introduzione, il sistema operativo RTEMS è stato ed è attualmente utilizzato in numerosi domini applicativi, l’ambito che spicca maggiormente sotto questo punto di vista è di sicuro quello spaziale, di cui fanno parte i due progetti descritti nei paragrafi seguenti. Come detto, però, le applicazioni pratiche di questo sistema sono davvero tante, troviamo progetti in ambito militare, industriale, di ricerca scientifica e persino progetti in campo sportivo, come la famosa BMW S1000R che partecipa ancora oggi al mondiale Superbike ed è stata guidata negli anni scorsi anche dal connazionale Marco Melandri: la moto in questione utilizza RTEMS per loggare i dati dell’engine control unit, più precisamente è presente un logger in esecuzione su RTEMS che va a collezionare una serie di dati a una velocità di 2 MB/s per l’analisi delle performance del veicolo, dopodiché il data logger usa il sistema per ottenere un comportamento ottimale e con un’alta percentuale di affidabilità nell’operazione di memorizzazione dei dati, i quali saranno ovviamente di fondamentale importanza per lo sviluppo e il miglioramento delle performance del veicolo. 4.1 Solar Dynamic Observatory (SDO) Il Solar Dynamic Observatory è un telescopio spaziale lanciato con successo dalla NASA l’11 febbraio 2010 per studiare il Sole, progettato per restare in orbita cinque anni, ha come obiettivo principale quello di investigare sull’influenza dell’attività solare sulla terra. In realtà SDO fa parte di un programma più ampio chiamato “NASA’s living with a star” (LWS), di cui è stato il primo progetto messo in atto. Analizzando gli obiettivi principali di questa sonda in maniera più approfondita, scopriamo che il progetto ha due finalità 24 fondamentali: studiare come viene generato e com’è strutturato il campo magnetico solare, e capire in che modo quest’energia magnetica viene convertita e rilasciata nello spazio sotto forma di vento solare e particelle energetiche. I sistemi real-time in generale vengono molto utilizzati in applicazioni di questo tipo, in quanto c’è la necessità di catturare una serie di informazioni ed elaborarle in un tempo prefissato, in questo caso si è scelto di utilizzare RTEMS per gestire le operazioni di I/O della sonda: il satellite dispone, infatti, di cinque processori chiamati radiation hardened coldfire CPU, sui quali gira il sistema operativo trattato all’interno di questo elaborato; abbiamo a disposizione quindi delle CPU Coldfire, derivate dalla famiglia del famoso Motorola 68000 e utilizzate soprattutto in sistemi embedded, in questo caso però sono state opportunamente modificate per essere hardened, vale a dire con lo scopo di minimizzare l’impatto di possibili vulnerabilità, migliorando di fatto la sicurezza complessiva. RTEMS, quindi, risulta particolarmente utile soprattutto per gestire le operazioni di I/O, di conseguenza si occupa di elaborare e sincronizzare i dati derivanti dai vari sensori e strumenti della sonda, il tutto con l’affidabilità assicurata dall’utilizzo di un sistema real-time; in maniera più specifica, la strumentazione scientifica del satellite è costituita da tre elementi fondamentali: • Uno strumento chiamato Extreme Ultraviolet Variability Experiment che misura l’emissione di radiazione ultravioletta con cadenza regolare e con un alto tasso di precisione, ed è proprio da qui che nasce l’esigenza di avere processi che terminano la loro esecuzione in un determinato intervallo di tempo. • Un altro strumento chiamato Atmospheric Imaging Assembly si occupa invece di fornire un’immagine piuttosto dettagliata del disco solare nelle differenti bande dell’ultravioletto. • L’Helioseismic and Magnetic Imager è l’ultimo elemento di particolare importanza della sonda che studia la variabilità dell’attività solare e le sue componenti magnetiche. Questi tre elementi collaborano tra loro scambiando e memorizzando informazioni in maniera affidabile e precisa grazie al sistema operativo RTEMS. 25 4.2 Electra Un altro progetto particolarmente rilevante che fa uso di RTEMS è senz’altro Electra, un SDR (Software Defined Radio) che, in linea con gli altri software appartenenti a questa categoria, permette di costruire dei ricevitori radio lavorando quasi completamente a livello software e non più hardware, con un supporto multistandard poiché chiaramente il software è riprogrammabile e particolarmente flessibile. Electra è stato sviluppato dal “Jet Propulsion Laboratory” situato a Pasadena (California), ed è diventato il sistema software al centro delle missioni spaziali su Marte dall’Agosto del 2005 grazie al Mars Reconnaissance Orbiter (MRO). Questi software sono in grado di inoltrare i dati ed eseguire misurazioni di alta precisione radiometrica, Electra, infatti, è una parte fondamentale dell’infrastruttura per i dispositivi di questo tipo, in quanto permette di trasmettere comandi dalla terra alla superficie di Marte e di restituire dati scientifici ed ingegneristici attraverso gli MRO. Entrando più nello specifico per quanto riguarda l’architettura di Electra, si dispone in linea generale di un processore Sparc V-7 25 Mhz e alcuni Megabyte di memoria centrale, quindi si ha a disposizione una dotazione hardware piuttosto modesta, ma che, di fatto, permette di avere abbastanza potenza computazionale e memoria a sufficienza per ospitare un filtro di navigazione real-time: è proprio grazie ai bassi requisiti richiesti da RTEMS, in termini di RAM e CPU, che questo sistema operativo risulta un’ottima base software per Electra, come se non bastasse le funzionalità messe a disposizione da questo SDR vanno ben oltre quelle che sono le reali capacità dell’hardware a disposizione, tutto ciò grazie al sistema operativo real-time utilizzato; a questo proposito utilizzando queste caratteristiche di Electra e RTEMS molto parsimoniose in termini di risorse, è stato possibile utilizzare le altre risorse hardware per scopi differenti, come ad esempio il fatto che numerosi dati radiometrici dopo essere stati elaborati vengano resi disponibili localmente in Electra, anziché essere trasferiti sul Bus dati. Tra i primi progetti che hanno fatto uso di Electra c’è stato di sicuro Phoenix, un lander stazionario che ha permesso di studiare il polo nord di Marte nel 2008, raccogliendo dei dati che saranno di importanza fondamentale per individuare le zone utili da esplorare durante le prossime missioni su questo pianeta del sistema solare. 26 Conclusioni Durante l’elaborato sono stati presi in considerazione alcuni aspetti fondamentali per il funzionamento di RTEMS, ma anche per qualsiasi altro sistema operativo Real Time, come lo scheduling e il ciclo di vita dei task. Ovviamente tutto ciò che abbiamo detto fino ad ora, per essere utilizzato, deve essere messo in pratica attraverso un’operazione di Building, termine che indica la compilazione e il deployment del sistema operativo sulla board di destinazione. Tutto ciò prevede l’utilizzo di una workstation per la crosscompilazione del codice da eseguire, che può essere sia di tipo Linux che Windows grazie a dei tool messi a disposizione dall’azienda, un Debugger per il download e il monitoraggio del file eseguibile, e infine la board dove dovrà essere eseguito il sistema operativo per quella particolare applicazione, eventualmente emulata per eseguire particolari prove prima della messa in pratica del progetto. Da qui si capisce come sia estremamente semplice compiere piccoli test di progetti anche piuttosto complessi che utilizzano RTEMS, ed è proprio questa semplicità e apertura del codice, di cui abbiamo parlato durante l’introduzione, unita alle esigue risorse hardware richieste dal sistema, che fanno di RTEMS uno dei sistemi operativi real-time maggiormente utilizzato sia per progetti indipendenti che finanziati e di particolare importanza o criticità, così come abbiamo potuto scorgere nel corso dell’ultimo capitolo. 27 Bibliografia [1] RTEMS Real Time Operating System (RTOS), http://rtems.org, 26 Aprile 2014 [2] G.Buttazzo, Sistemi in Tempo Reale, Pitagora Editrice, 404. [3] NASA – Mars Exploration Program, http://mars.jpl.nasa.gov, 26 Aprile 2014 28