Top Banner
Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica Elaborato finale in Sistemi Real Time Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time Anno Accademico 2011/2012 Candidato: Andrea Primativo matr. N46/246
43

Tesi Andrea Primativo

Feb 20, 2017

Download

Documents

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Tesi Andrea Primativo

Facoltà di Ingegneria

Corso di Studi in Ingegneria Informatica

Elaborato finale in Sistemi Real Time

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Anno Accademico 2011/2012

Candidato:

Andrea Primativo

matr. N46/246

Page 2: Tesi Andrea Primativo
Page 3: Tesi Andrea Primativo

Indice

Introduzione 4

Capitolo 1. Architettura di Sistema 6

1.1 Microkernel 71.1.1 Scheduling 71.1.2 Timer 9

1.1.3 Interrupt 9

1.2 Process Manager 121.2.1 Process Management 121.2.2 Memory Management 13

1.3 Adaptive Partitioning 141.3.1 Adaptive partitioning thread scheduler 151.3.2 Critical thread 16

1.4 High Availability 17

1.4.1 HA Client-side Library 181.4.2 HA Manager 18

1.5 Inter Process Communication 191.5.1 Message-Passing 19

1.6 Character I/O 21

1.7 Filesystem 23

Capitolo 2. QNX Momentics IDE & tools 24

2.1 Comunicazione Host-Target 25 2.2 System Profiler Tool 26

III

Page 4: Tesi Andrea Primativo

2.3 Application Profiler Tool 27

Capitolo 3. Esempio di utilizzo di Momentics IDE 31

3.1 Creazione Processi 31 3.2 Monitoraggio Processi 35

Conclusioni e sviluppi futuri 41

Bibliografia 43

IV

Page 5: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Introduzione

Sono sempre di più i campi in cui sono necessarie prestazioni real time. Ciò è dovuto sia

alla nascita di nuove esigenze applicative come il voip o lo streaming, sia all’enorme

evoluzione dell’hardware, in termini di costo e dimensioni, che ha consentito un

processo di automazione e digitalizzazione in svariati ambiti.

La necessità di base è quella di ottenere un servizio che sia garantito in termini di tempo

e prevedibilità.

In un passato non troppo lontano lo sviluppo di un sistema realtime prevedeva molto

spesso soluzioni “ad hoc”, ad esempio era di uso comune far interagire le applicazioni

direttamente con l’hardware in modo da eliminare tutte le fonti di non determinismo

introdotte ad esempio dal sistema operativo.

Al giorno d’oggi un tale approccio non solo è sconsigliabile in quanto contrario ad ogni

principio dell’ ingegneria del software, ma è praticamente irrealizzabile data l’elevata

complessità raggiunta degli odierni sistemi.

Si è reso quindi necessario l’utilizzo di sistemi operativi opportunamente progettati per

poter operare in un ambiente realtime, i cosiddetti RTOS (Real Time Operating

System).

Tali sistemi non solo sono in grado di garantire tempi di risposta molto bassi ma, cosa

più importante, anche un elevato grado di prevedibilità e determinismo.

Esistono ormai molti RTOS, sia open-source sia commerciali che, sebbene offrano lo

stesso servizio, sono spesso profondamente diversi tra loro rendendone ognuno più

adatto a talune applicazioni anzichè altre.

La scelta dell’RTOS da utilizzare in un determinato sistema è molto delicata, infatti ci

sono molti aspetti da considerare, non ultimi le certificazioni (a quali standard è

conforme), o i tools che tale sistema mette a disposizione.

Page 6: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Insomma una buona scelta può rappresentare un valore aggiunto per il sistema nel suo

complesso, mentre una scelta non adatta può comportare il fallimento dell’intero

progetto.

In questo elaborato analizzeremo l’RTOS QNX, che si propone come soluzione

altamente scalabile e flessibile e allo stesso tempo affidabile, adatta ad una vasta gamma

di applicazioni.

Page 7: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Capitolo 1

Architettura di sistema

QNX è un prodotto della Quantum Software System, una società canadese fondata da

due studenti dell’università di Waterloo nel 1982, anno del primo rilascio di QNX. In

pochi anni tale RTOS si guadagnò la fama di sistema altamente robusto e affidabile e

infatti è stato usato in molte applicazioni industriali.

Verso la fine degli anni ’80 il kernel venne completamente riscritto decidendo di

utilizzare lo standard POSIX. Il risultato fu QNX 4.

Neutrino è invece l’attuale versione del kernel QNX, scritto verso la fine degli anni ’90

e costantemente in aggiornamento, offre supporto nativo ad architetture SMP ed è

completamente conforme allo standard POSIX.

La scelta caratterizzante di QNX è quella di adottare un’architettura a microkernel che

sia molto flessibile in modo da potersi adattare semplicemente alle più disparate

esigenze e che sia contemporaneamente robusta. Infatti solo le funzioni fondamentali

sono implementate a livello kernel, mentre il resto delle funzionalità offerte (File

System, Device Drivers, Networking, ecc.) sono implementate in moduli separati che

girano a livello utente.

Un aspetto molto importante di QNX è la vasta gamma di certificazioni che gli sono

riconosciute, infatti oltre ad offrire completa aderenza allo standard POSIX è in

possesso delle seguenti certificazioni:

ISO 9001:2008

IEC 62304 Software Life-Cycle for Medical Device

IEC 61508 Safety Integrity Level 3

Common Criteria ISO/IEC 15408 Evaluation Assurance Level (EAL) 4+

POSIX PSE52 Realtime Controller 1003.13-2003

OpenGL ES

Page 8: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

E’ anche grazie a queste certificazioni che QNX è utilizzato in numerosi ambienti safety

critical, soprattutto in campo medico. Infatti esiste in commercio un’estensione del

kernel QNX ottimizzato per apparecchiature mediche: QNX Neutrino RTOS for

medical device.

Inoltre QNX Neutrino è molto diffuso nei sistemi di controllo industriale, nel settore

automotive, in sistemi per il controllo del traffico, nel settore aerospaziale e addirittura

in alcuni sistemi di controllo di reattori nucleari.

Infine il BlackBarry Tablet OS, il sistema operativo utilizzato dal tablet PlayBook, è

basato su QNX Neutrino.

1.1 Microkernel

Il microkernel implementato da QNX

(modulo procnto) è scritto quasi

completamente in C e implementa i servizi

fondamentali per la gestione dei thread e

Page 9: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

per garantire il funzionamento realtime.

Sostanzialmente i servizi offerti da tale microkernel sono lo scheduling, lo scambio di

messaggi, fondamentale per permettere la comunicazione tra i vari moduli aggiuntivi, la

gestione delle interruzioni e la gestione dei timer.

L’intera struttura del microkernel è realizzata in modo da porre un limite superiore al

tempo di esecuzione di una sequenza di istruzioni durante la quale le interruzioni sono

disabilitate, garantendo così un certo grado di prevedibilità.

1.1.1 Scheduling

Il thread è l’unità di schedulazione in QNX e quindi un processo deve contenere almeno

un thread.

Lo scheduler di QNX è uno scheduler basato su priorità, in particolare ci sono 256

livelli di priorità e lo scheduler sceglie sempre il thread “pronto” che ha la priorità

maggiore.

Esiste una coda separata per ogni livello di priorità, dove i thread pronti attendono di

essere schedulati. Solitamente ogni coda è gestita in maniera FIFO, tuttavia possono

esserci delle eccezioni, ad esempio quando un thread che si risveglia da una receive

bloccante con un messaggio per lui, esso è messo in testa alla coda relativa alla sua

priorità e non alla fine.

Per quanto riguarda le politiche di scheduling QNX ne implementa tre:

FIFO

Round Robin

Sporadic Scheduler

La politica Sporadic Scheduler risulta di particolare rilievo. Essa infatti è

un’implementazione del concetto di sporadic server, e infatti è consigliata proprio per

gestire richieste aperiodiche. E’ addirittura necessario adottare tale politica per le

richieste aperiodiche nel caso sia stato effettuato un test di schedulabilità sui task

periodici che girano nel sistema, in modo da non compromettere la fattibilità dello

Page 10: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

scheduling.

Inoltre essa può essere utilizzata per gestire task hard realtime, in quanto con tale

politica è assicurato che un thread abbia a disposizione un certo tempo di calcolo

all’interno del suo periodo (deadline) e ciò equivale a garantire (nei limiti della

fattibilità, che va comunque verificata in fase di progetto) che un task termini entro la

propria deadline.

Analizziamone il comportamento: ad ogni thread viene associata una capacità iniziale

C, un periodo di replenishment T e una Low priority.

Un thread esegue per un tempo C alla sua priorità nominale. Quando C si esaurisce la

sua priorità viene abbassata a Low priority. Dopo un tempo T la capacità C si “ricarica”

e la sua priorità è riportata a livello nominale.

Inoltre c’è da dire che il numero di replenishment è limitato in un dato periodo in modo

da non sovraccaricare il sistema a seguito ad esempio di overrun di attivazione di task

aperiodici.

Si noti che ogni thread nel sistema può eseguire usando una qualsiasi delle politiche

implementate e, infatti, tramite le primitive pthread_getschedparam(),

pthread_setschedparam() e pthread_setschedprio() si possono conoscere e cambiare

sia la politica di scheduling di un thread sia la sua priorità.

Si noti che le politiche RR e FIFO sono usate solo tra thread di pari priorità. In OGNI

CASO quando un thread a priorità maggiore diventa pronto prelaziona l’eventuale

thread a priorità minore che sta eseguendo.

1.1.2 Timer

Un aspetto di rilievo del microkernel QNX è la possibilità di usufruire del set di

funzionalità di timing definite dallo standard POSIX.

Di grande rilievo è il timer “cyclical”, ossia un timer che genera interruzioni

periodicamente.

E’ evidente come tale timer sia fondamentale nella gestione di task periodici, può essere

Page 11: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

infatti utilizzato per svegliare un task che dopo aver eseguito le sue operazioni torni a

bloccarsi fino al periodo successivo.

1.1.3 Interrupt

Uno dei tanti aspetti importanti in un sistema realtime è legato alle interruzioni, in

particolare i tempi di latenza legati ad esse.

I tempi di latenza di interesse sono due:

Latenza di interrupt, ossia il tempo che intercorre dall’istante in cui l’hardware

segnala l’interruzione all’istante in cui la prima linea di codice dell’interrupt handler è

eseguita. E’ necessario che questo tempo sia il più piccolo possibile. QNX si preoccupa

di renderlo tale, infatti le interruzioni sono quasi sempre abilitate e la latenza di interrupt

in questo caso è estremamente ridotta. Tuttavia alcune sezioni di codice impongono la

disabilitazione delle interrupt ritardando quindi l’ esecuzione dell’ handler; in questo

caso la latenza di interrupt nel caso peggiore è legata al tempo di esecuzione della più

lunga sezione di codice da eseguire ad interrupt disabilitate, tale tempo di esecuzione in

QNX è molto piccolo[1].

Latenza di scheduling, ossia il tempo che intercorre tra l’ultima istruzione

dell’interrupt handler e la prima istruzione del driver. Ciò equivale solitamente ad un

cambio di contesto e, sebbene sia un tempo più grande rispetto alla latenza di interrupt,

anche in questo caso QNX assicura che è un tempo molto ridotto, si pensi infatti che un

contex switch relativo a un processo in QNX Neutrino è più veloce di un contex switch

relativo a un thread in un sistema Unix [1].

Ovviamente QNX Neutrino offre pieno supporto alle interrupts innestate.

1.2 Process Manager

Page 12: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Il Process Manager è un’entità che, assieme al microkernel, è fondamentale per

l’esecuzione dei processi. Entrambe queste unità sono contenute nello stesso modulo

(procnto), essenziale per il runtime.

Le principali responsabilità del process manager riguardano la gestione dei processi

(process managment) e la gestione della memoria (memory managment).

Analizziamo questi due aspetti.

1.2.1 Process Managment

Per quanto riguarda la gestione dei processi la principale responsabilità del process

manager è la creazione dinamica di nuovi processi.

Per tale scopo sono rese disponibili diverse funzioni:

posix_spawn(), definita dallo standard POSIX tale funzione permette la creazione di

un processo specificando il programma che sarà eseguito da tale processo.

E’ l’equivalente di una fork() seguita da una exec(). Tuttavia la posix_spawn()

risulta molto più efficiente di tale combinazione in quanto non ha necessità di

ricopiare lo spazio di indirizzamento del processo padre (cosa che avviene tramite la

fork() ).

spawn(), tale funzione effettua sostanzialmente le stesse operazioni della

posix_spawn(), ma è implementata direttamente da QNX Neutrino e permette di

controllare dei parametri quali “scheduling policy” e “priority” che con la

posix_spawn() non sono accessibili.

fork().

vfork().

exec().

Sebbene siano disponibili anche le funzioni fork(), vfork() ed exec(), come si è detto,

risulta più conveniente usare una spawn() quando si vuole creare un nuovo processo

che dovrà eseguire un programma differente da quello del padre. Tuttavia tali funzioni

sono presenti soprattutto per una questione di portabilità (verso sistemi che non

Page 13: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

supportano la posix_spawn() ).

1.2.2 Memory Managment

Un aspetto caratteristico di QNX è proprio la gestione della memori in quanto, a

differenza della maggior parte degli RTOS, esso fornisce protezione della memoria

anche a runtime, tramite l’utilizzo di una MMU (che ormai viene fornita in molti

processori embedded).

L’utilizzo di una MMU comporta sicuramente degli svantaggi in termini di overhead e

prevedibilità, tuttavia l’avanzamento della tecnologia smussa tale aspetto, rendendo i

vantaggi di un ambiente protetto (dal punto di vista della memoria) di gran lunga

superiori agli svantaggi. In sostanza implementare protezione della memoria a runtime

permette di raggiungere livelli di robustezza ben superiori rispetto al caso di memoria

non protetta, al costo di un piccolo peggioramento delle performances.

Nello specifico il modello a protezione completa offerto da QNX prevede la rilocazione

del codice di un processo in uno spazio di indirizzamento virtuale privato che può

variare da 2 a 3.5 GB utilizzando appunto una MMU per la mappatura degli indirizzi

logici negli effettivi indirizzi fisici.

La memoria è gestita con la tecnica della paginazione su domanda e, nei sistemi che lo

supportano, la dimensione delle pagine può essere variabile, il che può comportare dei

vantaggi: l’uso di pagine di dimensione elevata permette di diminuire le entry di TLB

(Translation Lookaside Buffer) ottenendo quindi una minore probabilità di TLB miss e

aumentando di conseguenza le performances.

Essendo QNX Neutrino “fully compliant” allo standard POSIX, esso prevede un

meccanismo di memory locking utile per evitare le latenze dovute al caricamento on-

demand di una pagina non presente in memoria.

Un ultimo aspetto da considerare per quanto riguarda la gestione della memoria è la

frammentazione. QNX Neutrino adotta un algoritmo di allocazione della memoria

Page 14: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

fisica che cerca di ridurre al minimo tale fenomeno, tuttavia la frammentazione è

inevitabile in un ambiente dove i processi possono essere caricati dinamicamente e

quindi il memory manager implementa un algoritmo di deframmentazione.

Essendo comunque la procedura di deframmentazione onerosa in termini di overhead

c’è la possibilità di disabilitarla (di default è abilitata).

1.3 Adaptive Partitioning

Adaptive partitioning è un meccanismo di scheduling unico presentato da QNX.

Esso prevede di dividere i task presenti nel sistema in partizioni (insieme di task) ed

assicurare ad ogni partizione una percentuale minima di risorse (tempo di CPU).

Questo meccanismo è davvero interessante in quanto in condizioni di carico normali si

comporta come uno scheduler hard realtime, mentre in condizioni di carico elevate

impone dei limiti sul tempo di CPU di cui una partizione può usufruire, garantendo

comunque che la minima percentuale necessaria sia rispettata[2]. In altre parole offre

una implicita gestione dei sovraccarichi.

Page 15: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

1.3.1 Adaptive partitioning thread scheduler

Adaptive partitioning thread scheduler è un thread scheduler opzionale che garantisce a

gruppi di thread (partizione) una percentuale minima di utilizzo della cpu (budget).

Tale scheduler si comporta diversamente a seconda dello stato del sistema, in

particolare si possono distinguere i seguenti casi:

Underload: ogni partizione utilizza una percentuale di utilizzo minore del budget

nominale. In questo caso il thread scheduler semplicemente si comporta come lo

scheduler QNX Neutrino standard scegliendo il task da eseguire come il task a

priorità maggiore tra tutti quelli presenti nel sistema (tra tutte le partizioni).

Free Time: questa condizione si verifica quando una partizione non utilizza per

niente tempo di CPU. In questo scenario lo scheduler può “cedere” il tempo

inutilizzato ad un’ altra partizione che lo richiede, in particolare tale tempo sarà

assegnato alla partizione in cui risiede il thread a priorità maggiore. Ovviamente

questo comportamento potrebbe non essere sempre desiderabile e quindi è possibile

imporre che il tempo in eccesso non sia dato al thread più prioritario ma sia diviso

equamente tra le partizioni in rapporto al loro budget nominale.

Full Load: è lo stato in cui si trova il sistema quando tutte le partizioni utilizzano

interamente il loro budget. In questo caso lo scheduler divide il tempo di CPU tra le

partizioni in rapporto ai loro budget nominali. Ovviamente quando una partizione

richiede più tempo di quanto gli sia permesso, tale tempo non gli è concesso.

Si noti che in questo caso lo scheduler potrebbe non rispettare la politica di

scheduling adottata in maniera globale: se infatti una partizione ha esaurito il suo

budget, anche se ci fosse un thread pronto ad elevata priorità in tale partizione, esso

non sarebbe eseguito, lasciando spazio, ad esempio, ad un thread a più bassa priorità

che si trovi in una partizione che abbia ancora budget disponibile.

1.3.1 Critical threads

Page 16: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Si è visto che quando una partizione utilizza tutto il suo budget non gli è più permesso

eseguire (per un certo tempo). Evidentemente questo potrebbe non essere accettabile se

all’interno di quella partizione c’è un thread hard realtime fondamentale per il sistema

che si vorrebbe venisse eseguito nonostante la sua partizione sia “out-of-budget”.

Fortunatamente tale situazione è prevista. In particolare è possibile definire un thread

come critico. Tale thread potrà eseguire anche se la partizione cui appartiene ha

terminato il suo budget nominale, a patto che tale partizione disponga di un budget

“critico”.

Ricapitolando per garantire a thread hard realtime ad elevata priorità di eseguire, anche

in condizioni di carico elevato, nel rispetto delle loro deadline sono introdotti i concetti

di thread critico e budget critico.

E’ ancora possibile che un thread hard realtime non riesca ad eseguire e a non terminare

quindi entro la propria deadline?

Ovviamente questo può succedere se la partizione utilizza anche tutto il suo critical

budget.

QNX assume che tale condizione derivi da un errore di design. Infatti un errore

nell’assegnazione dei budget o un test di schedulabilità sbagliato possono essere la

causa di una deadline miss.

In un tale scenario la partizione è in bankruptcy. Neutrino permette di scegliere tra una

serie di comportamenti che il sistema dovrà adottare quando si verifica una bankruptcy:

Default: semplicemente non permette più alla partizione che ha esaurito il suo

critical budget di eseguire fino a quando non gli sarà assegnato nuovo budget

Force a reboot: Il sistema viene riavviato. Utile più che altro in fase di testing.

Notify: Notifica tramite l’invio di un segnale che una partizione è in stato di

bankruptcy.

Cancel: setta a zero il budget della partizione in oggetto. Il budget rimarrà tale fino a

quando non verrà cambiato manualmente (da shell ad esempio).

Concludendo l’adaptive partitioning thread scheduler è utile sotto molti punti di vista.

Page 17: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Può essere usato, infatti, per garantire un comportamento predicibile anche in situazioni

di overload, inoltre può essere utile per “limitare” applicazioni non sicure (di terze parti

ad esempio) in modo da evitare che monopolizzino la CPU [2].

Infine offre un’ottima gestione dell’ hard realtime grazie al meccanismo dei “critical

thread”.

1.4 High Availability

Il termine High Availability (HA) sta ad indicare la capacità di un sistema di rimanere

attivo per un prolungato intervallo di tempo senza interruzioni[6].

Affinché un sistema supporti HA è necessario che sia basato su un’opportuna

architettura, sia hardware che software.

Dal punto di vista software QNX Neutrino si propone, tra l’altro, come un sistema

operativo a supporto dell’ HA. In effetti un’architettura a microkernel è di per se una

soluzione molto robusta in quanto non solo separa le applicazioni utente da quelle

kernel, ma “protegge” il kernel anche dai task di sistema stessi: si pensi ad esempio al

fallimento del modulo che si occupa del filesystem. In un’ architettura monolitica ciò

comporterebbe il fallimento dell’intero kernel mentre in una ambiente a microkernel ciò

non sarebbe vero, il resto del sistema infatti continuerebbe a lavorare mentre potrebbero

essere intraprese opportune contromisure per provvedere al fallimento di quel

determinato modulo.

Tuttavia QNX Neutrino non si basa solo sulla sua robusta architettura ma offre un

supporto esplicito all’High Availability mediante due specifici moduli:

HA client-side library

HA Manager

1.4.1 HA client-side library

HA client-side library è una libreria che reimplementa svariate funzioni di I/O della

standard C library in un’ottica HA. In particolare è pensata per garantire un

Page 18: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

“meccanismo automatico e trasparente per il recovery” [6].

Ad esempio un client in comunicazione con un server può decidere di rendere tale

connessione HA; così facendo se la connessione dovesse cadere a causa ad esempio di

una momentanea mancanza di connettività la connessione verrebbe ristabilita in maniera

completamente trasparente tramite delle routine standard definite dalla libreria HA o

comunque tramite routine programmate dall’utente stesso.

1.4.2 HA Manager

L’HA Manager (HAM) offre dei meccanismi per monitorare i componenti (servizi o

processi) del sistema ed effettuare, in caso di fallimento di uno di tali componenti, un

graduale ripristino della sua normale attività. Ovviamente (HAM) provvede a tener

traccia di tutti gli eventi salienti avvenuti durante la vita dell’intero sistema.

A questo punto potrebbe sorgere spontanea la domanda: “Cosa accade se è l’HAM

stesso a fallire?”.

La risposta in effetti è molto semplice: HAM non è soggetto a fallimenti interni! Ciò è

ottenuto grazie ad una soluzione tanto semplice quanto efficace: associato ad un HAM

c’è sempre un “Guardian”, ossia un processo sempre pronto a occupare il posto dell’

HAM nel caso in cui quest’ultimo dovesse fallire. Dato che i due processi (HAM e

Guardian) condividono i dati tramite memoria condivisa il Guardian può sempre

riprendere dallo stato in cui l’HAM si è interrotto.

Si noti che il Guardian prima di prendere il posto dell’ HAM crea un nuovo processo

Guardian in modo che non ci sia mai un HAM senza un Guardian.

1.5 Inter Process Communication

La comunicazione tra processi è un aspetto particolarmente importante in QNX

Neutrino in quanto non solo le varie forme di IPC devono essere utilizzate dai processi

applicativi, ma perché anche la comunicazione tra i processi di sistema e il microkernel

avviene tramite scambio di messaggi.

Page 19: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

QNX Neutrino mette a disposizione vari tipi di IPC, tra cui le classiche shared memory,

le code di messaggi POSIX, Pipes e FIFOs, che sono disponibili tramite processi esterni

(tranne shared memory che è implementata nel contesto del Process Manager).

Inoltre altri due tipi di IPC più basilari sono implementati direttamente all’interno del

nucleo: signaling e message-passing. In questo elaborato ci soffermeremo solamente sul

message-passing in quanto rappresenta la base della comunicazione col micrkernel.

1.5.1 Message-passing

In sostanza tale tecnica è basata su tre primitive fondamentali:

MsgSend()

MsgReceive()

MsgReply()

Il nome di tali primitive è auto esplicante, tuttavia c’è da dire che mentre la MsgSend() e

la MsgReceive() sono bloccanti, la MsgReply() è non bloccante.

In realtà non necessariamente la MsgReceive() comporta un bloccaggio: consideriamo

un semplice scenario dove un thread client invia un messaggio ad un thread server.

Se il server effettua la MsgReceive() dopo che il client ha invocato la MsgSend() allora

il server non subirà alcun bloccaggio; potrà quindi elaborare il messaggio e rispondere

con una MsgReplay(). Per quanto riguarda il client, esso resterà sempre bloccato dopo

aver inviato una MsgSend() in attesa di una MsgReplay(); tuttavia c’è da fare una

distinzione: se la MsgSend() è effettuata prima della MsgReceive() il client sarà bloccato

nello stato SEND_BLOCKED, in seguito alla MsgReceive(), sebbene il client continui a

rimanere bloccato il suo stato cambia e diventa REPLY_BLOCKED. Diventerà infine

READY quando il server effettuerà la MsgReply().

Se, al contrario, la MsgSend() è invocata dopo la MsgReceive() il client si bloccherà, ma

direttamente con stato REPLY_BLOCKED, fino a diventare READY in seguito ad una

MsgReplay().

In realtà in QNX uno scambio di messaggi non avviene logicamente tra due thread bensì

tramite un canale. Quindi un server che desidera ricevere messaggi creerà un canale al

Page 20: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

quale uno o più client possono “attaccarsi”.

Per quanto riguarda le prestazioni della tecnica del message-passing esse sono

praticamente comparabili con la velocità della memoria fisica, in quanto l’invio di un

messaggio altro non comporta che la copia del messaggio dallo spazio di indirizzamento

del sender a quello del receiver.

Onde evitare il fenomeno dell’inversione di priorità QNX Neutrino associa alla tecnica

del message-passing il meccanismo di priority inheritance. Infatti il receiver di un

messaggio eseguira, per il tempo necessario all’elaborazione del messaggio (in pratica

fino all’invio della MsgReply() ), alla priorità del thread sender.

Un aspetto molto importante e caratteristico del message-passing implementato da

Neutrino è che esso può facilmente essere esteso in manienra del tutto trasparente a

target che non sono fisicamente sullo stesso host. Infatti tramite il framework Qnet,

ossia un insieme di librerie per il networking nativo, è possibile virtualizzare un network

in modo del tutto trasparente facendo comunicare due host tramite lo scambio di

messaggi.

1.6 Character I/O

Elevate prestazioni per quanto riguarda le comunicazioni con dispositivi di I/O a

“carattere” sono desiderabili in un sistema realtime, infatti l’utilizzo di tali dispositivi

Page 21: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

potrebbe far degenerare le prestazioni dell’intero sistema (in termini di prestazioni

realtime) se non opportunamente migliorato.

QNX Neutrino adotta una tecnica per la gestione del character I/O simile a quella dei

sistemi UNIX, infatti ogni dispositivo è mappato in un apposito file (solitamente nella

directory /dev).

E’ previsto un apposito modulo, char-io, per la gestione di tutti i dispositivi di I/O.

Come si può immaginare questo modulo esegue al di fuori del kernel e implementa le

classiche API POSIX per la comunicazione con i dispositivi a carattere, ma non solo;

infatti sono presenti funzioni non previste dallo standard che possono tornare utili in un

sistema realtime al fine di migliorarne le prestazioni.

Sostanzialmente il modulo char-io può essere visto come un processo gestore in

quanto si pone tra le applicazioni software e i driver relativi ai vari device, riducendo al

minimo le responsabilità di questi ultimi.

Tale implementazione per la gestione dei file cerca ridurre al minimo l’overhead

massimizzando il throughput; in particolare ciò è possibile grazie a queste due regole:

In seguito ad una richiesta di lettura, l’interrupt handler mette il dato letto in

una coda. Ora il driver verrà schedulato soltanto se c’è una richiesta di lettura

E tale richiesta può essere effettivamente soddisfatta.

Quando un’operazione di lettura va buon fine, sarà direttamente il driver a

comunicare il risultato all’applicazione. In questo modo il dato è copiato una

volta sola.

Sebbene non si sia scesi nello specifico del sottosistema dedicato ai device, si intuisce

che anch’esso è stato opportunamente ottimizzato per garantire prestazioni adeguate ad

un sistema realtime, mantenendo tuttavia un’architettura semplice e leggera.

Page 22: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

1.7 Filesystem

In QNX Neutrino è possibile usufruire di una vasta gamma di filesystem diversi. In

questo modo si aggiunge un ulteriore grado di elasticità al sistema, che può utilizzare un

filesystem anziché un altro a seconda delle esigenze. Ancora, è possibile che più

filesystem siano presenti contemporaneamente nel sistema e che anzi collaborino tra di

loro senza che ciò comporti un grosso overhead. Essendo, ancora una volta, il/i

filesystem eseguiti al di fuori del kernel, essi possono essere aggiunti o rimossi a

runtime senza alcun bisogno di riavviare l’intero sistema.

Page 23: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

In tabella sono riportati i vari filesystem supportati da QNX Neutrino.

Embedded Disk Network Other

Flash Devices

NOR Flash

NAND Flash

RAMTemporary storage

POSIX – QNX Filesystem

Ext2 - Linux

FAT 12, 16, 32 – Windows/DOS

NTFS (read only) - Windows

ISO9660, Joliet – CD-ROM Devices

HFS+ (read only) - Apple Mac OSX

UDF - CDs and DVDs

NFS Unix connectivity

CIFSMicrosoft connectivity

Compression

Add compression / decompression to any file system

Page 24: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Capitolo 2

QNX Momentics IDE & Tools

Qnx Momentics è un IDE, basato su Eclipse, messo a disposizione degli sviluppatori

dalla Quantum Software System.

Esso rappresenta uno strumento imprescindibile non solo per la creazione di software

per sistemi che utilizzano QNX Neutrino, ma anche per la manutenzione e il

monitoraggio di tali sistemi. Infatti il kit di sviluppo incorpora diversi tool per il

profiling sia del sistema che dei singoli processi in modo da tenere sempre sotto

controllo l’ambiente di runtime. Tale operazione di monitoraggio è possibile grazie al

servizio di comunicazione tra il target e il sistema host dove gira l’ IDE che, sia chiaro,

non necessariamente (anzi quasi mai) si trovano sulla stessa macchina.

Sebbene Momentics rappresenti un ambiente integrato che agevola lo sviluppo del

software, in questa trattazione si vuole dare maggiore rilievo ad altri aspetti della suite

di sviluppo quali: la comunicazione tra sistema host e target, il System Profiler Tool, l’

Application Profiler Tool. Infatti tali componenti sottolineano il fatto che QNX è un

sistema operativo specializzato nel gestire sistemi integrati che svolgono funzioni

critiche e quindi devono essere monitorati con particolare cura e soprattutto in maniera

remota.

2.1 Comunicazione Host-Target

Per sistemi Windows e Linux la comunicazione tra l’IDE e il target può avvenire sia

tramite IP sia tramite connessione seriale.

Per quanto riguarda la comunicazione IP è ovviamente necessario che i due end-point

(Host e Target) si trovino sulla stessa rete. Affinche un’effettiva comunicazione possa

Page 25: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

avvenire il Target deve opportunamente essere configurato per gestire la connessione IP

eseguendo il tool qconn. E’ interessante notare che due target che sono connessi

tramite Qnet possono entrambi comunicare con l’IDE utilizzando lo stack TCP/IP di

uno qualsiasi di essi. Una volta connessi è possibile per l’IDE comunicare con il sistema

target. In particolare a questo punto è disponibile il pannello “system information” che

fornisce in primo luogo una veduta d’insieme del sistema evidenziando l’utilizzo totale

di memoria e i processi in esecuzione. Inoltre per ogni processo è possibile analizzare

nello specifico il suo utilizzo di memoria, ossia della sua memoria virtuale,

evidenziando le varie aree: stack, heap, area dati e memorie condivise.

Infine un altro strumento interessante è il target filesystem navigator che ci permette di

navigare all’ interno del filesystem del sistema target.

Page 26: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

2.2 System Profiler Tool

Il System Profiler è un tool che permette di collezionare informazioni sul sistema target

e riportarle all’IDE. Tale tool si basa sulla estensione del microkernel Neutrino

denominata “instrumented microkernel” (proncto-instr); infatti tale modulo

utilizza dei meccanismi che permettono il profiling dell’intero sistema, il tutto senza

ovviamente compromettere le prestazioni. Sostanzialmente si può dire che System

Profiler fa uso delle informazioni ottenute dall’instrumented microkernel e le riporta

all’IDE per analizzarle.

Il System Profiler Editor mette a disposizione diversi pannelli di presentazione. Di

particolare interesse è il “summary pane”, che ci da informazioni sull’ utilizzo di cpu

sia in generale che per ogni processo.

Più nello specifico il grafico “system activity” divide il tempo di utilizzo della CPU

nelle seguenti categorie indicando quanto tempo, in percentuale, è stato utilizzato per

ogni categoria:

Idle: tempo di esecuzione del thread idle

Interrupt: tempo speso servendo interrupts

System: tempo speso gestendo kernel calls

User: tempo utilizzato da thread non idle meno il tempo utilizzato per kernel calls e

interrupt handler

La vista “process&thread activity” ci mostra invece l’utilizzo di CPU per ogni

Page 27: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

processo o thread in esecuzione nel sistema specificando per ognuno di essi:

Tempo di esecuzione

Tempo di attesa nello stato READY

Tempo di bloccaggio

Numero di kernel calls

Numero di messaggi scambiati

Inoltre fornisce un grafico dell’utilizzo generale della CPU.

A questo punto si potrebbe essere interessati a sapere per esempio la causa di un

eventuale picco di utilizzo evidenziato dal grafico, in particolare se esso è attribuibile ad

un determinato processo. In questo caso può risultare utile il pannello “CPU usage” che

ci mostra graficamente in maniera molto semplice l’utilizzo di CPU associato ad ogni

processo. E’ anche possibile evidenziare più processi contemporaneamente.

Un ulteriore utilizzo che può essere fatto del system profiler è, ad esempio l’analisi dei

tempi di latenza delle interrupt. Un’analisi del genere è coadiuvata dal pannello

“timeline”. Qui infatti sono riportati tutti gli eventi “loggati” dall’ instrumented

microkernel ordinati temporalmente e divisi per processo.

Infine c’è da dire che il file di log generato dall’intrumented microkernel può arrivare a

contenere milioni di eventi di interesse, e può risultare quindi particolarmente difficile

trovarne uno in particolare. Fortunatamente il tool System Profiler mette a disposizione

funzioni di filtering che permettono di “navigare” più agevolmente all’ interno del file

di log concentrandosi solamente su eventi di particolare interesse.

2.3 Application Profiler Tool

L’Application Profiler tool permette di monitorare le prestazioni di una particolare

applicazione senza la necessità di “seguirla” linea per linea, e può essere quindi

utilizzata per migliorarne le prestazioni individuando ad esempio quelle aree di codice

che incidono negativamente sull’efficienza. Questo tool offre diversi tipi di profiling:

Page 28: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Statistical profiling: in questa modalità il tool campiona ogni millisecondo il

processo durante la sua esecuzione registrando l’indirizzo dell’ istruzione

attualmente eseguita. In questo modo riesce a farsi un’idea “statistica” di quali

aree di codice impegnino di più la CPU. Ovviamente tale analisi, per sua natura,

può risultare affetta da errori statistici. Si noti che questo tipo di analisi non

comporta alcuna aggiunta di codice particolare utile a raccogliere informazioni.

Instrumented profiling: questa modalità di profiling prevede invece l’aggiunta

di codice supplementare (inserito direttamente dal compilatore), tuttavia permette

un’analisi più precisa che riesce a riportare anche informazioni “call-pair”, ossia

riesce a capire quale funzione chiama quale altra funzione.

Postmortem profiling: le informazioni ricavate da un’applicazione

“instrumented” sono raccolte in un file .out che una volta importato nell’ IDE

può fornire una rappresentazione grafica di tali informazioni. Come si intuisce

dal nome grazie a tale file è possibile un’analisi postmortem, tuttavia non

permette di ottenere tutte le informazioni ottenibili da un’analisi a runtime.

Per analizzare i dati ottenuti da un profiling, sia postmortem che a runtime, è possibile

utilizzare la “application profiler view”, mostrata nelle immagini in basso. In questo

pannello è possibile selezionare un item (es. un file .c) appartenente all’applicazione da

analizzare e a questo punto avremo una schermata (riquadro in basso a destra della

prima immagine) dove al codice sorgente è correlato un grafico (le linee colorate

affiancate alle linee di codice), in particolare:

Le barre verdi rappresentano la percentuale di tempo utilizzato nel contesto di una

funzione calcolata sulla percentuale totale associata al processo.

Le barre arancioni rappresentano la percentuale di tempo speso su quella

determinata linea di codice calcolata sulla percentuale totale associata al processo.

Le barre blu infine, rappresentano la percentuale di tempo speso su quella

Page 29: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

determinata linea di codice calcolata questa volta sulla percentuale di utilizzo della

particolare funzione cui appartiene quella linea.

Per ogni dato item selezionato nella application profiler view è possibile aprire tre

ulteriori viste:

Sampling information: tale vista elenca tutte le funzioni presenti nell’item

selezionato nella application profiler view e per ognuna di esse riporta (riquadro in

basso a sinistra della prima immagine):

Tempo di CPU speso nel contesto di quella funzione

Numero di chiamate

Tempo medio di esecuzione per ogni chiamata

Thread Processor Usage: per ogni thread presente nell’item riporta il tempo di

esecuzione, sia in secondi che in percentuale al tempo di utilizzo totale del processo

(riquadro in alto a destro della prima immagine).

Call counts: questa vista include tre pannelli (seconda immagine):

Call pairs: per ogni funzione indica da chi è stata chiamata e per quante volte (es.

funzione: sort; chiamata da: main; numero di volte: 10).

Call graph: un grafico che visualizza la serie di chiamate a funzione.

Call pair details: per la funzione selezionata nel call graph indica da chi è stata

chiamata, per quante volte, e la lista delle funzioni chiamate dalla funzione in

oggetto.

Page 30: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Page 31: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Capitolo 3

Esempio di utilizzo di Momentics IDE

In questo capitolo verrà mostrato un esempio di utilizzo dell’IDE. Verranno infatti

creati due semplici task periodici che agiranno rispettivamente da client e server

scambiandosi messaggi. Verrà dato rilievo alle primitive utilizzate per l’impostazione

del timer e a quelle relative allo scambio di messaggi. Si analizzerà poi il

comportamento dei due processi tramite i tool messi a disposizione dall’ IDE.

Nel seguente paragrafo saranno riportati soltanto i segmenti di codice di interesse.

3.1 Creazione Processi

Di seguito è riportato lo spezzone di codice relativo alla creazione del canale per la comunicazione:

Lato server

Lato client

Si noti per prima cosa che per la creazione e per l’attach non sono state utilizzata la

classica funzione ChannelCreate() e ConnectAttach(), bensì name_attach() e

name_open().

Queste ultime due funzioni in sostanza permettono di creare un canale e associargli un

nome ( name_attach() ) e di utilizzare tale nome per attaccarsi al canale (name_open() ),

rendendo l’uso di questa soluzione di gran lunga più adatto alla comunicazioni di

processi indipendenti tra loro. In questo caso ATTACH_POINT è una macro definita

if ((attach = name_attach(NULL, ATTACH_POINT, 0)) == NULL)

if( (msg_channel_id = name_open(ATTACH_POINT, 0)) == -1)return EXIT_FAILURE;

Page 32: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

come “server_channel”, attach è una variabile di tipo puntatore a name_attach_t,

una struttura definita in sys/dispatch.h che conterrà, tra l’altro l’id del canale

creato tramite la name_attach().

Prima di analizzare il codice relativo all’inizializzazione del timer è opportuno

soffermarsi su un aspetto importante riguardante la gestione di quest’ultimo.

QNX permette di associare particolari tipi di eventi allo scadere del timer; in particolare

ogni volta che il timer scade possono accadere tre cose:

Viene consegnato al processo cui è associato il timer un PULSE, ossia un particolare

tipo di messaggio.

Viene consegnato al processo cui è associato il timer un SIGNAL, inteso nel senso

POSIX del termine.

Viene creato un nuovo thread.

Nel nostro caso si è scelta la prima opzione, quindi ogni volta che il timer scadrà il

processo riceverà un PULSE che lo risveglierà dal suo stato RECEIVE_BLOCKED.

Ovviamente per fare in modo che ciò accada sono necessarie delle impostazioni

preliminari, tra cui la creazione di un canale dedicato alla ricezione di PULSE:

int pulse_channel_id;int pulse_id =0;struct _pulse pulse;struct sigevent event;struct itimerspec timer;

pulse_channel_id = ChannelCreate(0);

event.sigev_notify = SIGEV_PULSE;event.sigev_coid = ConnectAttach(ND_LOCAL_NODE,0,pulse_channel_id, 0, 0 );event.sigev_priority = getprio(0);event.sigev_code = 1023;event.sigev_value.sival_ptr = (void*)pulse_id;

timer_id = TimerCreate(CLOCK_REALTIME, &event);

timer.it_value.tv_sec = 1;timer.it_value.tv_nsec =0;timer.it_interval.tv_sec = 0;timer.it_interval.tv_nsec = 500000000;

timer_settime(timer_id, 0, &timer, NULL);

Page 33: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Quindi dopo aver opportunamente inizializzato la struttura event (in modo da settare

come notifica un PULSE) è possibile procedere alla creazione del timer tramite

TimerCreate(), che ha appunto in ingresso anche la struttura event.

A questo punto il timer esiste ma non è ancora avviato, ne tantomeno configurato. A

tale scopo è necessario inizializzare la variabile timer (di tipo struct

itimerspec). Tale struttura permette di impostare due parametri: il primo istante in

cui il timer scadrà (in termini relativi) e un intervallo che rappresenta il periodo dei

successivi istanti di tempo in cui scadrà il timer. Non necessariamente questi due valori

devono essere uguali. Si noti che i tempi sono espressi in secondi e nanosecondi.

Nell’esempio il timer scadrà una prima volta dopo 1 secondo e da quel momento in poi

ogni 0,5 secondi (500000000ns = 0,5s).

Infine è possibile far partire effettivamente il timer tramite l’istruzione timer_settime().

Ultimati tutti i settaggi i task possono svolgere i loro compiti all’interno di un ciclo

infinito (sono periodici); vediamo come viene svegliato un task all’inizio del suo

periodo:

Tramite la MsgReceivePulse(), un’ottimizzazione della MsgReceive() per i messaggi di

tipo PULSE, il processo rimarrà bloccato, una volta finito il suo ciclo di operazioni, fino

al ricevimento di un PULSE che sarà inviato proprio allo scadere del timer e cioè

all’inizio di ogni periodo.

Vediamo infine le primitive per lo scambio di messaggi:

Lato server:

pid = MsgReceivePulse(pulse_channel_id, &pulse,sizeof(pulse), NULL);

rcv_id=MsgReceive(attach->chid, &msg, sizeof(messaggio),NULL);

if(msg.header.type == _IO_CONNECT)MsgReply(rcv_id, EOK, NULL,0);

/* Elaborazione

*/

MsgReply(rcv_id, 0, &msg, sizeof(msg));

Page 34: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Si noti l’invio di una MsgReply() particolare quando l’header del messaggio

è di tipo _IO_CONNECT. In questo caso infatti il messaggio è la richiesta di

connessione del client e quindi la MsgReply() contiene un apposito flag

(EOK) che conferma la connessione. Questa è un’accortezza che si rende

necessaria se si utilizzano le funzioni name_attach() e name_open() per

instaurare la connessione.

Lato client:

Con ciò si conclude l’analisi delle principali funzioni utilizzate per la creazione dei due

processi.

3.2 Monitoraggio Processi

Una volta mandati in esecuzione i due processi è possibile utilizzare i vari tool che si

hanno a disposizione per monitorarne l’esecuzione. E’ possibile per prima cosa avere

una panoramica dell’intero sistema tramite le varie viste del pannello system

information (Capitolo 2, Paragrafo 2.1). Tuttavia una vista interessante che non è stata

mostrata prima è la vista “malloc information” che ci da informazioni sulla memoria

MsgSend(msg_channel_id, (void*) &msg, sizeof(messaggio), (void*) &msg, sizeof(messaggio));

Page 35: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

allocata dinamicamente ad un processo (Immagine 1 e 2).

I grafici mostrati nelle immagini sono relativi al processo client creato precedentemente,

infatti esso alloca ad ogni ciclo una quantità casuale di memoria.

Configurando opportunamente le due applicazioni al profiling tramite le opzioni di

compilazione dell’IDE è possibile sfruttare il System Profiler e l’ Application Profiler.

Le informazioni che si ottengono riguardo l’esecuzione dei processi e riguardo il

sistema sono riassunte in diversi pannelli.

Page 36: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Vediamo ad esempio il system summary e il CPU activity che abbiamo trattato nel

secondo capitolo.

Si possono distinguere i due processi utilizzati per questo esempio denominati

“client_es” e “server_es” con i relativi tempi di esecuzione. Inoltre il grafico di destra

ci mostra la percentuale di utilizzo della CPU. Tuttavia saremmo interessati a conoscere

le percentuali di utilizzo dei nostri due task in particolare e non solo la percentuale

globale. Si è allora ricorsi al pannello “CPU Usage” riportato di seguito.

Page 37: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

In rosso è evidenziata la percentuale di utilizzo del processo server, mentre in blu quella

del processo client. Sotto il grafico invece è riportata una tabella con i tempi di

esecuzione di ogni processo divisi per CPU (in questo caso una sola CPU).

Infine vorremmo essere in grado di analizzare il flusso di esecuzione dei due processi e

assicurarci che i periodi di attivazione siano rispettati. Ciò è possibile tramite il pannello

“Timeline”, in particolare quello riportato di seguito è stato ottenuto filtrando gli altri

processi presenti nel sistema e evidenziando soltanto i task dell’esempio e procnto (il

kernel).

Page 38: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Le linee nere verticali rappresentano le istanze dei nostri task. Si nota subito che

l’esecuzione risulta periodica come previsto, in particolare il timer “sveglia” i processi

ogni mezzo secondo proprio come impostato in fase di progetto.

Zoomiamo ora su una singola istanza di esecuzione dei processi e analizziamone il

flusso:

Nel grafico le comunicazioni inter-processo sono evidenziate da delle frecce, inoltre i

segmenti in verde scuro indicano che il processo è in stato READY, quelli in verde

chiaro che il task è in esecuzione, mentre i segmenti in blue indicano che il task è in

stato bloccato (es. RECEIVE_BLOCKED o REPLY_BLOCKED).

Nel caso specifico vediamo che il primo ad attivarsi è il client, che richiederà un

servizio dal server tramite l’invio di un messaggio (freccia blu dal client al server), il

server dopo aver elaborato il messaggio invia la reply al client (freccia verde dal server

al client). Infine entrambi i task si bloccano in attesa del PULSE che indichi lo scadere

del timer.

Osserviamo che posizionando il mouse su un particolare evento si apre una label che ne

riporta le informazioni salienti, come ad esempio il timestamp in cui si è verificato

l’evento e il nome dell’evento. In effetti tali informazioni sono quelle contenute nel log

file, il quale è riportato anche in una finestra, riportata di seguito, al di sotto del grafico:

Page 39: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Questa funzionalità offerta dall’IDE non solo può essere utile per analizzare il flusso di

esecuzione e verificare che i vincoli temporali siano rispettati, ma si potrebbe pensare di

utilizzarlo per calcolare statisticamente il tempo di calcolo di un dato processo. In tale

calcolo si dovrebbe tenere in conto però del tempo in cui effettivamente il processo in

oggetto esegue, ma anche del tempo di esecuzione di altri processi la cui esecuzione è

“imposta” dal processo in esame. Un esempio può essere proprio il processo client che

si è realizzato in questo capitolo, infatti il suo tempo di esecuzione non solo comprende

il tempo durante il quale il client utilizza la CPU, ma anche il tempo che impiega il

server ad offrire il servizio richiesto dal client.

In questo contesto può tornare utile un ulteriore pannello compreso nella vista

“Timeline” denominato “Client/Server CPU Statistics” riportato di seguito:

Page 40: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Si nota per ogni processo il tempo totale di CPU, il “Self Time”, che rappresenta il

tempo effettivo di utilizzo di CPU per il dato processo, e l’ “Imposed Time” che

rappresenta il tempo richiesto ad un altro processo da parte del processo in esame.

In questo modo è anche possibile individuare processi che, seppur non consumino

direttamente tempo di CPU, impongono un grosso carico sul sistema.

La panoramica degli strumenti offerti dall’IDE si ferma qui. Chiaramente le funzionalità

offerte da quest’ambiente integrato sono molteplici e non si limitano a quelle mostrate

in questo semplice esempio.

Page 41: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Conclusioni e sviluppi futuri

QNX nasce come un sistema operativo realtime che cerca di garantire elevate

prestazioni e grande robustezza ed affidabilità. In seguito all’analisi condotta si può

affermare che in effetti raggiunge questi obiettivi grazie a meccanismi intelligenti ed

eleganti. Un elemento di grande valore di questo sistema è sicuramente la sua

architettura che impiega un microkernel puro, che effettivamente fornisce poche

funzioni basilari. Questo aumenta notevolmente la robustezza del sistema a

malfunzionamenti degli altri componenti garantendo all’utente un elevato grado di

affidabilità. Ancora, grazie a questa struttura è possibile personalizzare il sistema in

modo da assicurare la massima flessibilità, in quanto caricando gli opportuni moduli è

possibile adattare il comportamento del sistema ad un particolare tipo di ambiente.

Un altro punto di forza di QNX è senza dubbio Momentics IDE che grazie ai vari tool

rappresenta un valore aggiunto di notevole interesse. Inoltre grazie alle tecniche di

cross-compilazione messe a disposizione da tale IDE e grazie al supporto di molteplici

architetture hardware, esso permette di sviluppare applicazioni che siano altamente

portabili. Abbiamo inoltre visto le varie tecniche di monitoraggio del sistema target,

funzione indispensabile, soprattutto quando si ha a che fare con sistemi critici.

Infine, aspetto non meno importante, la documentazione fornita è ampia ed esauriente e

permette a chiunque abbia dei concetti base del funzionamento di un sistema operativo

di capire con chiarezza i meccanismi adottati da QNX.

Concludendo credo di poter affermare che QNX si è mostrato effettivamente all’altezza

della sua fama e che il suo largo utilizzo in sistemi delle più svariate nature è

ampiamente giustificato dalla sua qualità.

Per quanto riguarda gli sviluppi futuri, sebbene QNX sia ampiamente affermato

soprattutto in ambito medico, sembra aprirsi un nuovo mercato in seguito

Page 42: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

all’acquisizione della Quantum Software System da parte di Research In Motion,

azienda produttrice degli smartphone BlackBerry. Infatti proprio l’ultimo sistema

operativo del nuovo tablet BlackBerry è basato su QNX, quindi a quanto pare

quest’ultimo potrebbe a breve diventare un concorrente di sistemi per smartphone quali

Android e iOS, e visti gli eccellenti risultati ottenuti da QNX fino ad ora chissà se fra

qualche anno non sarà presente nella maggior parte dei nostri dispositivi mobili.

Page 43: Tesi Andrea Primativo

Analisi del sistema operativo QNX per lo sviluppo di applicazioni real time

Bibliografia

[1] “QNX Neutrino RTOS, System Architecture”

[2] “QNX Neutrino RTOS, Adaptive Partitioning User’s Guide”

[3] “QNX Neutrino RTOS, Programmer’s Guide”

[4] “QNX Neutrino RTOS, Library References”

[5] “QNX Momentics Tool Suite, Integreted Development Environment User’s Guide”

[6] “www.qnx.com”