valutazione mediante fault injection di sistemi operativi
TRANSCRIPT
Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica
tesi di laurea specialistica
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo Anno Accademico 2008/2009 relatore Ch.mo prof. Domenico Cotroneo relatore Ing. Marcello Cinque candidato Ciro Manfellotto matr. 885/101
II
Indice Introduzione 1 Capitolo 1. Le Wireless Sensor Networks 4 1.1 Le WSN 4 1.2 Parametri di progetto per una WSN 6 1.3 Applicazioni delle WSN 7 1.4 Architettura di un nodo sensore 9 1.4.1 Sensing module 10 1.4.2 Unità di elaborazione 11 1.4.3 Unità di comunicazione 11 1.4.4 Alimentazione 12 1.5 Sistemi operativi per WSN 12 1.5.1 Il sistema operativo TinyOS 13 1.5.1.1 Architettura di TinyOS 15 1.5.1.2 Componenti in TinyOS 17 1.5.1.3 Il frame 18 1.5.1.4 I comandi 18 1.5.1.5 Gli eventi 19 1.5.1.6 I task 19 1.5.1.7 Lo scheduler 20 1.5.1.8 Operazioni split-phase 21 1.5.1.9 Active Messages 21 1.5.2 Il sistema operativo Mantis OS 22 1.5.2.1 Architettura di Mantis OS 23 1.5.2.2 Kernel e scheduler 24 1.5.2.3 Stack protocollare 25 1.5.2.4 Riprogrammazione dinamica 26 1.6 La dependability delle WSN 27 1.7 Guasti, errori e malfunzionamenti 28 1.7.1 Faults nel nodo sensore 29 1.8 Valutazione della dependability 30
III
Capitolo 2. Fault injection 32 2.1 Tecniche di fault injection 33 2.1.1 Harware-Implemented fault injection 33 2.1.2 Software-Implemented fault injection 34 2.1.3 Fault injection a tempo di compilazione e a tempo di esecuzione 35 2.1.4 Fault injection a livello assembly 37 2.2 Descrizione della tecnica SWIFI utilizzata e modifiche apportate 37 2.2.1 Descrizione della tecnica di injection 37 2.2.2 Guasti 39 2.2.3 Guasti in memoria dati 39 2.2.4 Guasti nel codice 40 2.2.5 Guasti nei registri del processore 41 2.2.6 Tecnica per la rilevazione dell’istante di injection 41 2.2.7 Modifiche apportate 44 Capitolo 3. AVR-INJECT Tool versione 2.0: la progettazione 51 3.1 AVR-INJECT Tool 51 3.2 Casi d’uso del tool 53 3.3 Component diagram 57 3.4 Class diagram 59 3.5 Sequence diagram 65 3.5.1 Sequence diagram n°1: nuovo esperimento 65 3.5.2 Sequence diagram n°2: esecuzione di un prog etto 67 3.6 Problematiche affrontate 69 Capitolo 4. AVR-INJECT Tool: esecuzione di un progetto 75 4.1 Creazione e configurazione di un progetto 75 4.2 Configurazione di uno studio step-by-step 78 4.3 Esecuzione di un progetto e visualizzazione dei risultati 83 4.4 Files generati dal tool 85 4.4.1 File Esp_*.od 86 4.4.2 File esp_avrora.txt 87 4.4.3 File esp_Memory.txt 87 4.4.4 Files esp_Profile.txt e esp_Calls.txt 87 4.4.5 File Trace.txt 88 4.4.6 File avr.sh 88 4.4.7 File avrGrep.sh 88 4.4.8 File Risultati.txt 89 Capitolo 5. Utilizzo del tool: analisi comparativa tra TinyOS e Mantis 90 5.1 Fault injection in Mantis OS 92 5.1.1 Code Error Injection 93 5.1.2 Memory Error Injection 97
IV
5.1.3 PC Error Injection 101 5.1.4 SP Error Injection 103 5.1.5 SR Error Injection 107 5.1.6 Mantis Total Error Injection 110 5.2 Fault injection in TinyOS 113 5.2.1 Code Error Injection 113 5.2.2 Memory Error Injection 117 5.2.3 PC Error Injection 121 5.2.4 SP Error Injection 124 5.2.5 SR Error Injection 127 5.2.6 TinyOS Total Error Injection 131 5.3 Risultati ottenuti con l’applicazione surge 133 5.3.1 Risultati totali in Mantis OS 134 5.3.2 Risultati totali in TinyOS 136 5.4 TinyOS vs Mantis OS 139 Conclusioni 143 Sviluppi futuri 144 Bibliografia 145 Sitografia 147
1
Introduzione
Gli sviluppi tecnologici, avvenuti negli ultimi anni nel campo dell’elettronica e
dell’informatica, hanno reso possibile lo sviluppo di reti di sensori senza filo (dette anche
WSN che è l’acronimo di Wireless Sensor Networks). In virtù delle loro caratteristiche,
esse possono essere utilizzate per una moltitudine di applicazioni nei campi più disparati:
tipiche applicazioni sono quelle per la rilevazione, il controllo, la comunicazione, la
sorveglianza e il monitoraggio sia in ambito militare che civile.
Le WSN possono anche essere utilizzate per applicazioni critiche, queste ultime si
differenziano dalle normali applicazioni per i requisiti di qualità ed affidabilità
estremamente stringenti. In questo caso è necessario garantire la dependability in quanto
un qualsiasi malfunzionamento potrebbe provocare gravi danni a persone e/o cose. Il
concetto di affidabilità esprime la capacità di una WSN di lasciare inalterate le proprie
funzionalità anche in caso di eventuali guasti di qualche nodo sensore oppure in seguito al
fallimento di una trasmissione (un pacchetto inviato non arriva a destinazione).
Il lavoro di tesi svolto può essere decomposto in due fasi: 1) modifica di un tool per
l’iniezione di guasti in microcontrollori per WSN; 2) utilizzo del tool per l’analisi
comparativa tra due sistemi operativi per WSN.
Il tool, realizzato in un precedente lavoro di tesi, utilizza una tecnica di iniezione a livello
assembly con inserzione di codice per iniettare guasti di tipo bit-flip di diversa natura
2
(Codice, Memoria, Program Counter e Status Register). Inoltre per il suo funzionamento è
utilizzato l’emulatore Avrora, che permette di emulare una rete di sensori senza filo i cui
nodi sono dei microcontrollori AVR.
Le modifiche apportate al tool durante la prima fase del lavoro di tesi comprendono:
l’ampliamento delle destinazioni dei guasti (aggiunta del registro Stack Pointer), la
correzione di alcuni problemi riscontrati e l’analisi automatica dei risultati che comprende
la classificazione degli errori riscontrati e la generazione dei relativi grafici.
Nella seconda fase del lavoro di tesi è stata svolta un’analisi comparativa tra due sistemi
operativi per reti di sensori senza filo: TinyOS e Mantis. In particolare, attraverso l’utilizzo
del tool, è stata realizzata una campagna di fault injection su due applicazioni simili (Blink
di TinyOS e blink_led di Mantis) allo scopo di valutare il comportamento dei due sistemi
operativi in presenza di guasti.
Il lavoro di tesi è strutturato in 5 capitoli; di seguito riportiamo una breve descrizione per
ogni capitolo.
Il capitolo 1 fornisce una panoramica delle WSN, in particolare si inizia con una
contestualizzazione necessaria a descrivere e valutare l’affidabilità nelle WSN. Si procede
poi con la descrizione di due sistemi operativi per WSN (TinyOS e Mantis) e si conclude
con l’introduzione del concetto di Fault Injection presentando a tal proposito le principali
problematiche della Fault Injection nelle WSN.
Il capitolo 2 descrive le principali tecniche di fault injection note, in particolare viene
analizzata in modo dettagliato la tecnica di iniezione utilizzata dal tool mettendo in
evidenza le modifiche apportate durante il lavoro di tesi.
Il capitolo 3 descrive la parte di progettazione della nuova versione del tool mettendo in
evidenza le novità introdotte, le modifiche apportate e le problematiche affrontate.
Vengono presentati e descritti, per gli scenari più significativi, alcuni casi d’uso per
illustrare il funzionamento del tool, il component diagram per evidenziare i componenti
principali che costituiscono l’applicazione, il class diagram ed alcuni sequence diagram.
3
Il capitolo 4 fornisce una descrizione dell’utilizzo del tool in cui si spiega come creare e
gestire un generico progetto dell’applicazione. Con l’ausilio di una sequenza di schermate,
che riportano i punti salienti dell’applicazione, è possibile capire come lavora il tool e
familiarizzare con l’interfaccia GUI che si presenta semplice e facile da usare per un
qualsiasi utente. Infine si descrivono brevemente i file generati da Avrora ed utilizzati per
l’analisi dei risultati.
Il capitolo 5 descrive la campagna di fault injection realizzata per l’analisi comparativa tra
TinyOS e Mantis, mettendo in evidenza gli obiettivi, le metriche utilizzate ed il piano degli
esperimenti. I risultati ottenuti sono mostrati in forma grafica utilizzando i grafici generati
dal tool.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
4
Capitolo 1
Le Wireless Sensor Networks
Il mondo delle reti di telecomunicazioni è in continua espansione, come testimonia la
capillare di diffusione delle reti ad estensione geografica (Wide Area Network). Da molti
anni si è intuito che il limite principale delle reti è costituito dalle infrastrutture necessarie
al loro funzionamento. Cavi e punti di accesso rappresentano un grosso ostacolo per
l’espansione della rete stessa, operazione che diventa alquanto costosa in termini di tempo
e risorse. Una valida soluzione in merito è rappresentata dall’utilizzo di reti ad hoc. Essa è
stata elaborata al preciso scopo di ottenere reti autoconfiguranti, che non necessitino di una
organizzazione gerarchica e soprattutto di infrastrutture. E’ indispensabile che reti di
questo tipo permettano di risolvere con efficacia problemi dovuti a guasti, spegnimenti e
mutamenti dell’ambiente operativo. Le reti di sensori senza filo, o Wireless Sensors
Networks(WSN) nascono alla stessa stregua delle reti ad hoc, focalizzandosi su
applicazioni di monitoraggio e controllo ambientale e strutturale.
Questo capitolo prima introduce al lettore le reti di sensori, focalizzando l’attenzione in
particolare sulle WSN (Wireless Sensor Networks) e poi descrive due tra i sistemi
operativi più utilizzati per questa tipologia di reti: TinyOS e Mantis.
1.1 Le WSN
Per comprendere cosa sia una rete di sensori definiamo innanzitutto un sistema distribuito.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
5
Un sistema distribuito è un sistema formato da un insieme di componenti dislocati su vari
calcolatori connessi tra loro attraverso una rete telematica e capaci di comunicare e
coordinare le loro azioni unicamente attraverso lo scambio di messaggi. Un sistema
distribuito è caratterizzato dalla concorrenza dei suoi componenti, dall’appartenenza a
diversi domini dei suoi componenti, da meccanismi di sincronizzazione e interazione basati
sullo scambio di messaggi, e dalla possibilità di guasti indipendenti dei suoi componenti.
Una rete di sensori è un sistema distribuito costituito da un insieme di nodi capaci di
ospitare sensori o attuatori, eseguire elaborazioni e comunicare tra loro attraverso
protocolli di rete multi-hop dove il messaggio giunge a destinazione dopo aver attraversato
un certo numero di nodi. Volendo dare una definizione un po’ più informale si può dire che
una Wireless Sensor Network è una rete costituita da un insieme di sensori distribuiti
nell’ambiente che cooperano tra di loro, mediante trasmissioni wireless (senza filo), allo
scopo di rilevare fenomeni fisici. Solitamente una WSN è costituita da una stazione base
(vedi figura 1.1) eventualmente connessa ad altre reti (mediante gateway) e da un certo
numero di sensori wireless (nodi). Il numero di sensori che costituiscono una rete può
variare da qualche decina a svariate migliaia di unità. Le informazioni raccolte vengono
poi inviate verso una stazione base, passando da un nodo all’altro secondo un protocollo
multi-hop ed infine trasferite, via internet o via satellite, verso un centro di raccolta.
Esistono configurazioni con più stazioni base mobili e i nodi inviano i loro dati verso un
sottoinsieme delle stazioni stesse.
Figura 1.1: Esempio di WSN
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
6
1.2 Parametri di progetto per una WSN
Per realizzare una buona WSN è necessario rispettare una metrica delle prestazioni. I
fattori che influiscono la progettazione delle reti di sensori senza filo sono vari, di seguito
descriviamo brevemente i fattori principali.
• Tolleranza ai guasti: è necessario innanzitutto garantire una tolleranza ai
guasti in quanto il mancato o errato funzionamento di alcuni nodi non deve
impedire lo svolgimento del task richiesto dall’utente.
• Topologia di rete: occorre saper scegliere un’opportuna topologia di rete in
base al luogo fisico in cui andrà posizionata la rete: i nodi possono avere una
disposizione di tipo mesh (a griglia), di tipo cluster (raccolti in sottoinsiemi)
oppure a stella (un nodo centrale di riferimento).
• Consumi: una WSN deve contenere i suoi consumi in quanto i nodi sono
provvisti di alimentazione autonoma (ad es. una batteria), tuttavia questa
alimentazione ha una durata limitata nel tempo quindi occorre anche saper
minimizzare il consumo dei dispositivi delle WSN. A tal proposito è lecito
ricordare che un dispendio energetico non trascurabile può essere dovuto ad
un malfunzionamento in una WSN: infatti in questo caso la rete deve
provvedere al reinstradamento dei pacchetti e all’individuazione di una nuova
topologia di rete.
• Scalabilità: una WSN deve essere scalabile cioè deve essere in grado di
lavorare con un numero di nodi elevato e consentire una semplice
aggregazione di nuovi nodi. Una rete di sensori senza filo può essere popolata
da decine o migliaia di nodi conservando in entrambi i casi una propria
stabilità e robustezza.
• Mezzi trasmissivi: la realizzazione di una discreta WSN è legata alla scelta
del mezzo trasmissivo da adottare. Dal momento che si tratta di una
comunicazione wireless (senza filo) tra i sensori, allora si possono usare gli
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
7
ultrasuoni, i raggi infrarossi oppure i segnali radio; nell’ultimo caso però
occorre tenere conto di particolari fenomeni fisici legati al mezzo trasmissivo
quali la riflessione, l’attenuazione o i cammini multipli dei segnali propagati.
• Prestazioni: misurare le prestazioni di una WSN significa valutare il suo
transfer rate (la velocità di trasferimento dei pacchetti tra i sensori), la sua
latenza (il tempo che intercorre tra la richiesta di inoltro di un pacchetto e
l’inizio dell’effettiva trasmissione del pacchetto) ed infine il Packet Error Rate
(la percentuale di generazione di pacchetti errati in un intervallo di tempo).
• Costo: dal momento che una rete di sensori senza filo può contenere fino a
migliaia di nodi, è bene valutare il giusto costo da investire. Occorre saper
scegliere il giusto rapporto qualità-prezzo e pertanto si cerca di spendere il
minimo per avere un prodotto efficiente ed efficace.
1.3 Applicazioni delle WSN
Le reti di sensori senza filo possono essere utilizzate nella realtà in diversi contesti che
spaziano dal controllo ambientale all’automazione casalinga, dalle applicazioni
commerciali ai servizi fino ad arrivare al settore sanitario. E’ possibile inoltre misurare una
vasta gamma di grandezze fisiche come l’umidità, la pressione, la temperatura, il suono,
l’intensità luminosa, le dimensioni di un oggetto, la presenza di oggetti in movimento e
anche la loro accelerazione. I sensori, grazie alle loro ridotte dimensioni, si adattano bene
ad ambienti ostili e inaccessibili (ad esempio in un bosco di una riserva naturale). Inoltre
grazie al loro elevato numero, risulta particolarmente facile monitorare grandezze in aree
relativamente ampie.
Nel controllo ambientale le WSN acquisiscono un ruolo fondamentale per seguire gli
spostamenti degli animali, ad esempio specie di animali protette, e per monitorare
determinate colture. Nel settore ambientale il principale ruolo ricoperto dalle reti di sensori
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
8
senza filo è costituito dalla segnalazione di incendi boschivi (numerosi soprattutto nel
periodo estivo) e quindi alla tempestività di inoltro del segnale d’allarme (ad esempio ad
un comando della guardia forestale o dei vigili del fuoco più vicino rispetto al luogo
dell’incendio).
Nel campo sanitario possiamo incontrare alcune applicazioni che usufruiscono delle WSN
per la realizzazione di interfacce per disabili oppure per il monitoraggio integrato dei
pazienti o in alcuni casi anche per il tele monitoraggio dei dati fisici di un individuo. Le
WSN vengono utilizzate anche per il monitoraggio del personale medico. In particolar
modo nelle applicazioni mediche esse vengono sfruttate per controllare determinati
parametri di un paziente quali la pressione sanguigna, la temperatura, le pulsazioni
cardiache, consentendo, qualora si riscontrasse un valore anomalo, la segnalazione e la
tempestività del soccorso da parte del personale medico. Quindi già da questi brevi esempi
è possibile immaginare quanto sia importante assicurarsi che un sensore sia tollerante ad
eventuali guasti che potrebbero generarsi, affinché non si verifichino conseguenze gravi
nella vita reale.
Nella Home automation si può pensare di avere una serie di elettrodomestici (forni a
microonde, frigoriferi, videoregistratori, lettori DVD etc). Questi possono interagire tra
loro e con una rete esterna, via internet o via satellite e consentono all’utente di comandare
facilmente gli elettrodomestici a distanza. In tal caso dunque le WSN vengono utilizzate in
ambienti intelligenti e non solo in casa ma anche negli uffici.
Nelle applicazioni commerciali si può pensare ad un ambiente lavorativo come ad un
ufficio nel quale viene erogata aria condizionata. Il monitoraggio dell’aria all’interno degli
uffici può essere eseguito proprio con una rete di sensori senza filo. Il flusso di aria
condizionata è controllato in maniera centralizzata; l’uso razionale dei sensori favorisce
una riduzione del loro consumo di energia.
Le reti di sensori wireless possono anche assumere un ruolo dominante nelle più comuni
attività militari come il comando, il controllo dei campi di battaglia, la rilevazione degli
spostamenti delle truppe nemiche, la sorveglianza e le operazioni di localizzazione dei
bersagli.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
9
Nel campo industriale le WSN possono essere utili per la guida e il controllo di robot nei
processi industriali oppure per la verifica delle categorie e della qualità di vari articoli
presenti in un grande magazzino.
Infine le reti di sensori senza filo si rivelano convenienti anche nel controllo del traffico di
autoveicoli (si pensi ad un tratto stradale critico).
La figura 1.2 illustra gli scenari di utilizzo delle WSN appena descritti.
1.4 Architettura di un nodo sensore
Una rete di sensori rappresenta un insieme di nodi sensore che formano una prestabilita
topologia. I nodi sono disposti all’interno di un’area in cui si osserva il fenomeno che si
vuole analizzare. Il numero di sensori che compongono una rete può variare da qualche
decina a svariate migliaia. Le informazioni raccolte vengono inviate ad una stazione base
(detta sink ), passando da un nodo all’altro secondo un protocollo multi-hop, ed infine
Figura 1.2: Scenari di utilizzo delle WSN
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
10
trasferite ad un centro di raccolta. Il nodo sensore può essere suddiviso in quattro moduli:
sensing module, unità di elaborazione, unità di comunicazione e alimentazione.
1.4.1 Sensing module
In questo contesto indicheremo con il termine sensore l’hardware di cui è dotato un nodo
per trasformare la grandezza fisica acquisita in un segnale elettrico che possa essere
elaborato (trasduttore). Un nodo può disporre di più sensori, anche di grandezze fisiche
diverse, che sono strettamente legate alla specifica applicazione; si possono avere ad
esempio sensori di luminosità, di pressione, di temperatura, di prossimità. La maggior parte
dei sensori, prevede inoltre la presenza di un blocco di conversione analogica-digitale
(ADC, Analog to Digital Converter), da utilizzare durante la fase di acquisizione del
segnale. All’aumentare della velocità di campionamento e del numero di bit del
convertitore analogico digitale, si ha un incremento dei consumi.
Figura 1.3: Architettura del nodo sensore
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
11
1.4.2 Unità di elaborazione
La presenza di una CPU permette di dotare il nodo della capacità elaborativa per gestire le
comunicazioni e le grandezze misurate. Il ruolo della CPU può essere svolto da diverse
tipologie di circuiti logici. Solitamente si preferisce adoperare un microcontrollore a basso
consumo, ma è possibile impiegare anche un FPGA (Field Programmable Gate Array), un
DSP (Digital Signal Processing) o un ASIC (Application Specific Integrated Circuit).
Un compito tipico del microprocessore in queste piattaforme è la verifica dell’effettiva
necessità di utilizzare le risorse: per preservare la carica della batteria il nodo deve
disattivare tutti i dispositivi come chip radio, timer, oscillatori, ogni volta questi non sono
utilizzati per le attività del nodo stesso. La gestione dei tempi e delle modalità del
passaggio dallo stato a basso consumo a quello di attività dei vari componenti è affidata al
microprocessore. Il microprocessore è spesso integrato con alcuni blocchi di memoria
ROM e RAM utilizzati per ospitare il codice eseguibile del sistema operativo e
dell’applicazione, ma immagazzina anche i dati acquisiti dai sensori ed elaborati
dall’applicazione. Alcune piattaforme possono essere dotate di memorie Flash aggiuntive,
connesse al microprocessore per mezzo di interfacce seriali. Queste memorie, solitamente
di capacità superiore rispetto alle memorie integrate con il microprocessore, possono essere
utilizzate per contenere parametri per la configurazione del nodo o altri dati.
1.4.3 Unità di comunicazione
La connessione è realizzata via radio, anche se per alcune particolari applicazioni sono
disponibili soluzioni alternative che impieghino ultrasuoni o comunicazioni ottiche.
Solitamente tra tutti i componenti del nodo, il chip radio è il dispositivo che consuma la
maggior parte dell’energia. Per ridurre il costo e il consumo energetico dei nodi, si
utilizzano tipicamente modulazioni ben consolidate e di bassa complessità, pagando un
costo in termini di capacità trasmissiva che è spesso limitata a qualche decina di kbit/s. Per
limitare ulteriormente il costo finale del dispositivo, la modulazione radio avviene
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
12
normalmente nelle bande comprese tra gli 868-870 MHz o nelle bande ISM (Industrial
Scientific Medical) attorno ai 900 MHz e ai 2,4 GHz, per le quali non è richiesta licenza
governativa.
1.4.4 Alimentazione
Dal momento che non vi è la possibilità di usufruire di una rete di distribuzione
dell’energia, è necessario che ciascun elemento della WSN sia equipaggiato con un sistema
autonomo di alimentazione. Attualmente l’unica soluzione diffusa è data dall’utilizzo di
pile elettrochimiche; questo è uno dei motivi per cui la progettazione delle reti di sensori è
centrata sul risparmio energetico. L’unica strategia di risparmio applicabile per ora è lo
spegnimento selettivo dei nodi per la maggior parte del tempo, in modo da ridurre il
consumo di potenza medio.
1.5 Sistemi operativi per WSN
A differenza delle tradizionali architetture hardware, dove si dispone di grandi quantità di
memoria, di complessi sottosistemi per la gestione dei dati di ingresso e d’uscita, di elevate
capacità di elaborazione e sorgenti di energia praticamente illimitate, nelle reti di sensori ci
troviamo a confronto con sistemi di piccole dimensioni, le cui fonti di energia sono
limitate, vi è scarsa quantità di memoria, e basse capacità di elaborazione. Sono necessarie
quindi soluzioni molto semplici ed efficienti e che soprattutto riducano notevolmente i
consumi di energia. Di conseguenza anche il sistema operativo risente di queste
limitazioni. Infatti un sistema operativo per reti di sensori senza filo deve possedere alcune
caratteristiche di base: deve avere ridotte dimensioni, basso consumo energetico durante
l’elaborazione e consumo pressoché nullo durante lo stato di idle del sensore, deve gestire
la concorrenza, deve implementare protocolli di rete a seconda della periferica di rete
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
13
utilizzata e tali protocolli devono essere poco dispendiosi ; il sistema operativo, inoltre,
deve fornire un’astrazione per i dispositivi hardware montati sul nodo sensore.
Per completezza ricordiamo che in letteratura si distinguono principalmente due approcci
allo sviluppo di sistemi operativi per reti di sensori senza filo:
• Sviluppare un sistema i cui componenti vengono compilati insieme
all’applicazione (come TinyOS (1) ). Questo di fatto consente una singola
applicazione in un dato momento, quindi permette di avere bassissimi
consumi (non esistono in genere context switch dal momento che gli scheduler
seguono una politica run to completion ) e sistemi molto piccoli (essendo
realmente inserite nel sistema solo le funzionalità richieste). Lo svantaggio
derivante da tale approccio è la limitata versatilità e i seri vincoli di
riconfigurabilità dell’applicazione.
• Sviluppare un sistema che includa i tradizionali strati di software dei sistemi
general purpose in versione ridotta (ad esempio Mantis [10]). In questo caso è
difficile tenere sotto controllo i consumi e le risorse impiegate, ma si
guadagna in versatilità, potendo eseguire più applicazioni in contemporanea.
1.5.1 Il sistema operativo TinyOS
TinyOS è un sistema operativo open-source real-time sviluppato per le reti di sensori senza
filo dalla Berkley University di California in collaborazione con il centro ricerche Intel.
TinyOS è concepito in modo da presentare caratteristiche di efficiente gestione energetica,
basso carico computazionale, ridotte dimensioni, modularità e supporto intensivo alla
concorrenza. TinyOS non è un sistema operativo nel senso tradizionale del termine, infatti
si differenzia in modo sostanziale dai sistemi operativi general-purpose in quanto si integra
direttamente con le applicazioni sviluppate. D’altro canto, come tutti i sistemi operativi,
TinyOS gestisce le risorse hardware e software ed esporta allo strato applicativo
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
14
un’astrazione dello strato hardware stabile e consistente, tale da sollevare gli sviluppatori
dall’onere di conoscere i dettagli di basso livello delle risorse fisiche. Una tipica
applicazione TinyOS based ha le dimensioni di una decina di KB, dei quali soltanto 400
byte competono al sistema operativo, ed è proprio alle dimensioni esasperatamente ridotte
che TinyOS deve il suo nome (infatti TinyOS significa sistema operativo piccolo). Tra gli
elementi più significativi di TinyOS spicca il modello di programmazione component-
based, codificato dal linguaggio NesC (un dialetto del C) ed il modello di esecuzione
event-driven come supporto alla concorrenza. TinyOS non possiede un kernel vero e
proprio, ma permette l’accesso diretto all’hardware, attraverso una Hardware Abstraction
Architecture.
E’ opportuno definire brevemente i concetti di task ed evento. Dicesi task un’attività
indipendente mentre l’evento è l’occorrenza di un fenomeno di interesse per uno o più
oggetti. I task sono atomici rispetto agli altri task e possono richiamare comandi, notificare
eventi o attivare altri task all’interno dello stesso componente. In TinyOS gli eventi sono
visti come delle interruzioni hardware: il componente di più basso livello trasforma
un’interruzione hardware in un evento per poi notificarlo ai livelli più alti.
La versione di TinyOS utilizzata per il lavoro di tesi svolto è la 2.0, e si tratta di una
versione successiva a quella adoperata dai precedenti lavori di tesi centrati sulle WSN. Le
novità introdotte, rispetto alla versione precedente, riguardano tre aree fondamentali:
1. Flessibilità e portabilità rispetto alle piattaforme
2. Robustezza ed affidabilità
3. Concetto di distribuzione di servizi
L’accresciuta flessibilità rispetto alle piattaforme è realizzata tramite l’articolazione in tre
layer dell’Hardware Abstraction Architecture e la nuova versione 1.2 del linguaggio NesC.
TinyOS 2.0, inoltre, migliora la robustezza e l’affidabilità ridefinendo alcune tra le
principali astrazioni e politiche delle precedenti versioni tra le quali: il processo di
inizializzazione, la coda dei task e, soprattutto, la gestione energetica. Infine, la nuova
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
15
nozione di distribuzione di servizi, paragonabile ad una API, semplifica notevolmente lo
sviluppo delle applicazioni.
1.5.1.1 Architettura di TinyOS
L’architettura di TinyOS 2.0 si basa sul principio delle astrazioni, attraverso le quali si
realizza una decomposizione in strati verticali ed orizzontali dei componenti del sistema
operativo.
Le astrazioni hardware, lo stack per la comunicazione, quello per i sensori e gli attuatori e
lo strato applicativo sono esempi di strati verticali. Gli strati che occupano, all’interno
dell’architettura del sistema, una posizione più bassa sono dipendenti dall’hardware ed
esportano verso l’esterno complesse interfacce per la gestione dei dispositivi fisici dei nodi
sensori. In modo duale gli strati che occupano posizioni più alte sono perfettamente
disaccoppiati ed indipendenti dai dispositivi fisici ed esportano interfacce più user-friendly.
Figura 1.4: Architettura di TinyOS 2.0
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
16
La decomposizione orizzontale si articola all’interno degli specifici sottosistemi. Essa
semplifica la portabilità, consentendo il riuso delle astrazioni in piattaforme diverse. La
decomposizione orizzontale è particolarmente evidente nello strato che realizza
l’astrazione hardware del nodo sensore. Tale strato infatti riflette perfettamente la
dimensione fisica di un nodo sensore realizzata da una composizione orizzontale di chip
standard. Modellando ciascun chip come astrazione platform-indipendent si abilita la
portabilità dei chip in piattaforme diverse. Al livello più basso dell’architettura del sistema
operativo troviamo l’Hardware Abstraction Architecture, ovvero, i componenti che
realizzano l’astrazione dei dispositivi hardware del nodo sensore.
Dalla figura 1.4 si nota la presenza di due stack differenti: communication stack e sensor
stack (che si riferisce sia ai dispositivi sensori che a quelli attuatori). In particolare i
componenti di più basso livello, che sono a diretto contatto con il canale radio, realizzano
lo stream di dati in uscita suddividendolo in pacchetti. Inoltre essi realizzano attività di
codifica di errori e scheduling del canale di comunicazione. Questi stessi componenti si
occupano, inoltre, della gestione dei pacchetti in arrivo e del loro smistamento nei buffer di
ingresso. I componenti di alto livello si occupano, invece, delle attività di gestione dei
buffer, dell’autenticazione, e realizzano il multiplexing della rete attraverso i diversi
componenti applicativi. Parallelamente al communication stack si sviluppa il sensor stack
che prevede meccanismi per l’interazione con i dispositivi sensori e con gli eventuali
attuatori.
Immediatamente sopra i sensor e comunication stack si collocano i componenti
implementati dall’utente per rispondere alle specifiche esigenze applicative. A livello più
alto troviamo, infine, il componente di sistema Main che include, a sua volta, un altro
componente imprescindibile per ogni applicazione, ovvero, il componente di Scheduler. Il
Main implementa la sequenza di boot del sistema operativo, quindi realizza
l’inizializzazione della piattaforma hardware e dei componenti software ed esegue il main
task loop.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
17
1.5.1.2 Componenti in TinyOS
Il modello di programmazione di TinyOS si basa su una particolare architettura a
componenti. Ciascun componente TinyOS è un’unità software indipendente. In particolare,
ogni componente è descritto in termini delle interfacce importate ed esportate e della sua
implementazione interna.
I componenti comunicano tra loro invocando comandi (gestiti da command handlers) e
sollevando eventi (gestiti da event handlers). Comandi ed eventi vengono eseguiti al livello
alto di priorità dello scheduler. A questi si aggiungono una serie di task che vengono
eseguiti ad un livello di priorità basso. Ogni componente inoltre contiene un frame che è
l’area dati del componente e viene allocata staticamente. Tipicamente gli eventi vengono
sollevati da componenti più vicini all’hardware (componenti di basso livello) verso
componenti meno vicini, mentre i comandi vengono invocati in verso opposto. I
componenti possono essere suddivisi in tre categorie: Hardware abstractions, questi
componenti mappano le funzionalità fornite via software sulle funzionalità fornite
dall’hardware creando un’astrazione dello stesso utilizzabile dai moduli superiori;
Synthetic hardware, questi moduli simulano il comportamento di hardware più sofisticato
di quello realmente presente sul sensore; High level software component, questi
Figura 1.5: Rappresentazione di un componente di TinyOS
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
18
componenti sono quelli di livello più alto e si occupano di eseguire algoritmi che
prescindono dal particolare hardware. Ad esempio un componente che legge/scrive un bit
su un canale radio è un’astrazione hardware, mentre un componente che compone 8 bit e li
invia a quelli di livello superiore è un hardware sintetico, mentre il componente che
implementa il protocollo di routing è un componente di alto livello.
1.5.1.3 Il frame
Il frame rappresenta l’area di memoria all’interno del quale il componente conserva i dati
relativi al suo stato. Si tratta, in particolare, di una struttura C-like allocata staticamente in
memoria a tempo di compilazione ed accessibile unicamente al componente stesso. La
preallocazione statica della memoria in fase di compilazione consente di conoscere a priori
la quantità di memoria richiesta dall’intera applicazione, ottimizzando cosi l’uso delle
risorse.
1.5.1.4 I comandi
In TinyOS i comandi sono richieste non bloccanti di servizi offerti dai componenti di
livello inferiore. Generalmente un comando deposita dei parametri all’interno del frame
locale, quindi attiva un task. Alternativamente un comando potrebbe a sua volta invocare
un altro comando di livello inferiore. A causa del limitato quantitativo di memoria del
frame, un componente può rifiutare un comando. Convenzionalmente un comando fornisce
un feedback al suo chiamante per mezzo di opportuni parametri di ritorno, informandolo
così del successo o meno dell’operazione richiesta. I comandi sono progettati nell’ottica di
ritornare immediatamente, svolgendo semplicissime funzioni di triggering su altri
componenti, i servizi richiesti dai comandi saranno, quindi, svolti concorrentemente
all’interno dei task del componente.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
19
1.5.1.5 Gli eventi
In generale, in un modello di programmazione ad eventi, occorre distinguere il concetto di
evento, inteso come accadimento significativo per il quale un’entità ha manifestato
interesse, dal concetto di notifica di un evento, inteso, invece, come annuncio
dell’accadimento di un evento inviato alle entità che hanno manifestato il loro interesse.
Ogni entità interessata ad un particolare evento implementa al suo interno un event
handler, ovvero una routine di gestione dell’evento stesso. In TinyOS gli event handler
sono direttamente o indirettamente legati agli eventi hardware del nodo sensore. Gli eventi
scaturiscono, infatti, da interrupt hardware notificati ai componenti direttamente connessi
con lo strato fisico del nodo. Generalmente un event handler deposita informazioni
all’interno del frame locale, quindi esegue un task. Alternativamente un evento notifica
l’accadimento dello stesso evento ai componenti di livello superiore oppure invoca un
comando di un componente di livello inferiore. Un evento, pertanto, sollecita un processo a
catena in grado di salire e scendere lungo il grafo dei componenti di un’applicazione
innescando attività collaterali. Al fine di evitare possibili cicli infiniti all’interno della
catena comandi/eventi, un comando non può, al suo interno, notificare l’occorrenza di un
evento. Gli eventi sono stati progettati nell’ottica di eseguire piccole quantità di calcoli e,
tipicamente, sono associati a condizioni di risveglio del nodo sensore; per tale motivo, è
necessario che gli eventi vengano eseguiti in tempi brevi, in modo da permettere ai nodi
sensori di ritornare nel loro stato di idle.
1.5.1.6 I task
I task costituiscono l’astrazione con la quale viene definita la mansione primaria di un
componente. I task non hanno diritto di prelazione su qualunque altra attività in corso, in
altri termini sono atomici rispetto agli altri task (politica di run to completition). Per
assicurare la concorrenza, i task possono essere, tuttavia, interrotti dalla notifica di un
evento. Ciascun task può, al suo interno, invocare comandi di componenti di livello
inferiore, segnalare eventi ai componenti di livello superiore, e schedulare altri task.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
20
Mentre il meccanismo dei comandi e degli eventi consente di realizzare computazioni
approssimativamente istantanee, i task non sono time-critical ed abilitano qualunque forma
di computazione che richieda un significativo numero di cicli elaborativi. E’ tuttavia,
fondamentale assicurare la terminazione di un task così da consentire il progresso delle
attività degli altri componenti. L’atomicità dell’esecuzione di un task consente una
notevole semplificazione del modello di concorrenza giacché libera dalla necessità di
protocolli di mutua esclusione per la protezione delle risorse e delle variabili allocate in
memoria da un task. TinyOS gestisce un unico stack allocato, a turno, all’unico task in
esecuzione in un dato istante. Lo scheduler standard di TinyOS esegue i task secondo una
politica FIFO (First In First Out). La CPU viene allocata ad un task solo dopo la naturale
terminazione del task attualmente in esecuzione. Questa scelta non esclude la possibilità di
implementare, secondo le necessità, politiche di scheduling differenti. Esiste, comunque,
un limite alla dimensione della coda dei task nello scheduler legato ai vincoli di memoria;
attualmente il numero di task accodabile è fissato a 255. Oltre ad ottimizzare l’utilizzo
delle risorse hardware, il modello di programmazione event-based limita sensibilmente il
consumo energetico, portando la CPU in uno stato di idle tutte le volte che non ci sono
mansioni da espletare; l’occorrenza di un evento risveglierà dunque la CPU da tale stato.
1.5.1.7 Lo scheduler
Il componente principale, l’unico sempre presente in ogni applicazione, è lo scheduler.
Esso lancia in esecuzione i task dei diversi componenti secondo una politica FIFO run-to-
completion, ossia un task non può interromperne un altro. Lo scheduling ha due livelli di
priorità: quello normale per i task e quello più alto per gli eventi, che possono interrompere
i task. Inoltre esistono livelli di priorità anche tra gli eventi stessi: un evento con priorità
più alta di quello attualmente in esecuzione può interrompere l’esecuzione dell’evento
corrente.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
21
1.5.1.8 Operazioni split-phase
In TinyOS, ogni operazione è una split-phase operation, ovvero l’invocazione di un
servizio e l’operazione di ritorno sono, in realtà, due funzioni separate. Per richiedere un
servizio ad un componente la procedura seguita è quella di invocare un comando sul
componente. Il comando avvia un task e ritorna immediatamente il controllo al
componente chiamante. Al termine del task viene notificato un evento sul componente che
ha richiesto il servizio. Nel modello di interazione split-phase operation, il componente
chiamante non attende attivamente la risposta del componente chiamato (busy waiting), ma
prosegue nelle proprie elaborazioni. Ricevuta poi la notifica dell’espletamento del servizio
con un evento (all’interno del quale possono essere incapsulati dei dati), interrompe
l’esecuzione di eventuali task ed elabora l’evento ricevuto. La semantica delle spilt-phase
operation consente di disaccoppiare il componente chiamante dal componente chiamato,
realizzando, così, un meccanismo di comunicazione asincrona ad accoppiamento lasco.
1.5.1.9 Active Messages
L’ active messages implementa un protocollo inaffidabile di livello data-link che si occupa
del controllo di accesso al mezzo e della comunicazione single-hop tra i nodi della rete.
Questo significa che un nodo equipaggiato con il solo sistema operativo può inviare
messaggi solamente ai nodi direttamente collegati ad esso tramite un mezzo trasmissivo,
mentre non può inviare messaggi a un qualsiasi nodo della rete, perché i protocolli di
routing sono implementati ai livelli superiori. Active messages è una tecnologia molto
leggera, infatti non specifica meccanismi di comunicazione orientati alla connessione, ma
prevede che ogni pacchetto sia un’unità indipendente. Essa consente di inviare pacchetti
verso un singolo nodo, specificando un indirizzo di 16 bit, oppure di inviare pacchetti in
broadcast, specificando l’indirizzo 0xFFFF. Il funzionamento di active messages consiste
nell’inviare al nodo destinazione un pacchetto che, oltre al campo dati, contiene
un’informazione che specifica il tipo di evento che deve essere generato sul nodo
destinazione a seguito della ricezione del pacchetto. Quando un nodo riceve un pacchetto,
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
22
esso viene elaborato dall’active messages, il quale individua il tipo di evento da generare,
incapsula il campo dati del pacchetto in un evento e invia la notifica di tale evento al
componente appropriato. Active messages consente di inviare più di 256 tipi di messaggi
diversi, ognuno dei quali associato a un differente gestore di evento. Questa caratteristica
permette a più reti o a più protocolli di alto livello di funzionare in concorrenza e senza
causare conflitti. Inoltre, l’active messages fornisce anche l’astrazione di 256 gruppi di
nodi differenti. Questa ulteriore funzionalità consente di suddividere una grande rete di
sensori in più sottoreti logicamente separate e tra di loro invisibili. Il sistema di
comunicazione su cui si basa active messages permette di eliminare il complesso utilizzo
di buffer delle implementazioni TCP/IP, ma il principale svantaggio dell’approccio è che
tutti i nodi comunicanti devono avere un componente in grado di gestire un ben preciso
tipo di eventi.
1.5.2 Il sistema operativo Mantis OS
Mantis OS (chiamato anche MOS) è un sistema operativo per reti di sensori senza filo,
progettato e sviluppato dalla Colorado University. Concettualmente MANTIS è opposto a
TinyOS, infatti esso ha la struttura di un sistema operativo general purpose, è organizzato a
livelli, è multithread e contiene uno scheduler preemptive con time slicing, utilizza
meccanismi di sincronizzazione attraverso sezioni in mutua esclusione, ha uno stack
protocollare standard per la rete e device drivers (l’architettura di Mantis verrà analizzata
in dettaglio nel prossimo paragrafo). Grazie al multithread e allo scheduler preempite in
Mantis è possibile, in un nodo sensore, intrecciare l’esecuzione di task complessi con
quella di task che hanno dei requisiti temporali stringenti. L’occupazione di memoria di
Mantis è ridotta infatti in un’immagine che non supera i 500 byte è contenuto il kernel, lo
scheduler e lo stack di rete. Il consumo energetico in Mantis è ridotto in quanto viene
utilizzato uno scheduler efficiente dal punto di vista energetico; infatti quando tutti i thread
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
23
attivi chiamano la funzione sleep() di MOS lo scheduler spegne il microcontrollore
riducendo notevolmente i consumi. Due interessanti caratteristiche di progetto di Mantis
sono: la flessibilità (supporto per piattaforme diverse) e la gestione dei sensori attraverso la
riprogrammazione dinamica da remoto. La versione attuale di Mantis, quella utilizzata per
il lavoro di tesi, è la 1.0 beta.
1.5.2.1 Architettura di Mantis OS
Mantis OS essendo un sistema operativo general-purpose, ha una classica architettura
multithread a strati, come mostrato in figura 1.6. Dalla figura si nota che i thread
applicativi sono separati dal sistema operativo sottostante attraverso le API. Inoltre grazie
alle API, Mantis permette il supporto a piattaforme differenti. Mantis OS (MOS) è
costituito da uno scheduler leggero ed efficiente dal punto di vista energetico, uno stack di
rete a livello utente ed altri componenti come i devide drivers.
Figura 1.6: Architettura di Mantis OS
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
24
1.5.2.2 Kernel e scheduler
Le funzionalità offerte dal kernel di MANTIS OS sono un sottoinsieme dell’interfaccia
POSIX, in particolar modo lo scheduler priority-based basato sull’algoritmo round-robin.
Per la sincronizzazione e la concorrenza il sistema supporta semafori sempre secondo lo
standard posix. L’obiettivo principale per il progetto del kernel di MOS è quello di
implementare questi servizi in modo efficiente sfruttando al meglio le risorse limitate del
nodo sensore. La risorsa più limitata in un nodo Mantis è la RAM. La memoria RAM è
divisa in due sezioni: statica, dove vengono allocate al momento della compilazione le
varabili globali; heap (la parte restante di RAM), dove vengono allocati i thread al
momento dell’esecuzione. Al momento in Mantis non è possibile allocare manualmente
memoria dinamica, questa limitazione è dovuta alle ridotte dimensioni della memoria e alla
necessità di avere una politica di gestione coerente e ben pianificata.
La principale struttura dati globale del kernel è la tabella dei thread che ha un’entry per
ciascun thread. Inoltre dato che questa tabella è allocata staticamente è fissato un numero
massimo di thread (di default è 12 e può essere modificato a tempo di compilazione) e un
livello massimo di overhead di memoria (120 bytes). Ogni entry della tabella occupa 10
byte e contiene: puntatore allo stack corrente, informazioni sui limiti dello stack (puntatore
base e dimensione), un puntatore alla funzione start del thread, il livello di priorità del
thread ed il puntatore al thread successivo (nel caso di utilizzo di una linked list). Il kernel
di Mantis mantiene liste di thread ready separate in base ai diversi livelli di priorità, inoltre
per ogni lista sono mantenuti due puntatori, quello alla testa e quello alla coda; questo
meccanismo semplifica le operazioni di aggiunta e cancellazione dalle liste.
Generalmente il cambiamento di contesto avviene in seguito alla ricezione da parte dello
scheduler di un interrupt temporizzato generato da hardware predisposto, tuttavia si può
avere anche in seguito ad operazioni con i semafori (operazioni in mutua esclusione). Gli
interrupt temporizzati sono gli unici gestiti dal kernel, tutti gli altri sono inviati
direttamente ai device driver associati; al momento il kernel di MOS non supporta interrupt
software.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
25
Oltre ai driver thread e agli user thread c’è anche un idle thread creato dal kernel allo
startup; l’idle thread ha una priorità bassa ed è eseguito quando tutti gli altri thread sono
bloccati e serve a limitare il consumo energetico impostando opportunamente alcuni
parametri del sistema.
1.5.2.3 Stack protocollare
Per quanto riguarda la comunicazione di rete, MANTIS OS prevede uno stack protocollare
strutturato su quattro livelli: fisico, MAC, network e applicazione. Il sistema è molto più
sofisticato e versatile di quello di TinyOS, infatti possono coesistere meccanismi di routing
diversi (unicast, flooding, multicast). I diversi livelli sono in esecuzione in thread separati,
con l’eccezione del livello fisico e di quello MAC che vengono eseguiti dallo stesso thread.
La lettura di un pacchetto di rete funziona con un sistema stop and wait. Infatti un thread
intenzionato a leggere un pacchetto dalla rete (tramite chiamata a mos recv) rimane
bloccato su un semaforo. Quando un pacchetto arriva (è disponibile) viene sollevato un
interrupt, quindi il device driver associato sblocca il semaforo. Non esiste il concetto di
connessione: l’invio e il routing vengono sempre effettuati separatamente per ogni singolo
pacchetto. Questo approccio rende l’interfaccia di rete più versatile, infatti il progettista del
software può sviluppare l’applicazione senza essere a conoscenza dei meccanismi di
routing utilizzati nella particolare rete sviluppata; inoltre è molto utile per la
riprogrammazione dinamica del sensore, in quanto per riprogrammare le funzionalità di
rete è sufficiente bloccare i thread dello stack in esecuzione ed eseguire i thread del nuovo
stack protocollare. Di contro questo sistema è prestazionalmente più scadente di Active
Messages (utilizzato in TinyOS), essendo l’elaborazione del singolo pacchetto più lunga, e
comportando un continuo cambio di contesto di esecuzione al momento della
comunicazione di rete (causando consumi maggiori).
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
26
1.5.2.4 Riprogrammazione dinamica
In base a delle ricerche effettuate, è stato dimostrato che i nodi sensori, dopo che sono stati
messi in esercizio sul campo, necessitano di una riconfigurazione o modifica. In
particolare, dato che le reti di sensori possono essere inserite in aree difficilmente
accessibili, la possibilità di poter effettuare una riconfigurazione dinamica da remoto
semplifica enormemente la gestione della rete. L’obiettivo di Mantis OS è quello di fornire
una riconfigurazione dinamica a differenti granularità: reflash dell’intero OS,
riprogrammazione di un singolo thread e cambiamento di variabili all’interno di un thread.
MOS include due modalità di riprogrammazione: programmazione semplice e
programmazione avanzata. Nella modalità di programmazione semplice, è richiesta la
comunicazione diretta ad un nodo Mantis (ad esempio collegamento attraverso la porta
seriale del sensore), in particolare l’utente deve solo collegare il nodo ad un pc ed avviare
la shell di Mantis. A questo punto (dopo un restart) MOS avvia un boot loader che cerca
eventuali comunicazioni dalla shell, in questo modo il nodo accetterà il nuovo codice
immagine che verrà scaricato dal pc attraverso la connessione diretta. Il boot loader
trasferisce il controllo al kernel di MOS o in seguito ad un apposito comando dalla shell
oppure se durante lo startup non è individuata nessuna shell.
La modalità di programmazione avanzata è utilizzata quando un nodo è stato già messo in
esercizio, di conseguenza tale modalità non richiede un collegamento diretto al nodo
sensore. In particolare, per fornire all’utente la possibilità di gestire i nodi da remoto
Mantis OS include il Mantis Command Server (MCS). Quindi un utente, attraverso un
qualsiasi dispositivo della rete dotato di terminale, può invocare il mantis command client
ed effettuare il login in un nodo sensore. Lo stesso MCS è realizzato come un thread
applicativo, ed è in ascolto sia sulla porta seriale che sull’interfaccia radio di comandi che
possono essere inviati sia dal kernel che dalle applicazioni. L’utente può visualizzare la
lista dei comandi supportati dall’MCS, può ispezionare e modificare la memoria del nodo,
cambiare le impostazioni di configurazione, eseguire o terminare programmi, visualizzare
la tabella dei thread e riavviare il nodo. Al momento MOS supporta solo il login remoto e
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
27
il cambiamento di variabili o parametri mentre è in realizzazione la riprogrammazione
dinamica dell’intero sistema operativo.
1.6 La dependability delle WSN
La dependability è di fondamentale importanza per i sistemi distribuiti e di conseguenza
anche per le reti di sensori senza filo. Essa è costituita da un insieme di attributi, quali:
affidabilità , sicurezza, manutenibilità e disponibilità .
Un sistema può ritenersi affidabile se è realizzato con capacità di rilevazione degli errori
(causati sia da guasti hardware che software), di localizzare ed isolare la causa degli errori
e di ripristinare il sistema.
La dependability si definisce come la capacità di fornire un servizio su cui si può fare
affidamento. Il sistema è quell’entità in grado di interagire con altre entità (es. altri
sistemi); il comportamento del sistema percepito dall’utente rappresenta il servizio, il quale
può ritenersi corretto (proper service) se è fedele alle specifiche funzionali altrimenti è non
corretto e in quest’ultimo caso si parla di malfunzionamento; il confine tra sistema ed
utente si definisce interfaccia e la particolare interfaccia sulla quale viene fornito il servizio
è definita come service interface.
Gli attributi di qualità che costituiscono la dependability sono cinque: Reliability,
Maintainability, Availability, Safety, Integrity. Vengono analizzati di seguito i primi
quattro:
1. Reliability: la reliability è definita come la probabilità che un servizio venga
fornito in modo corretto in un intervallo di tempo finito.
2. Maintainability: la maintainability è definita come la capacità di un sistema di
essere facilmente sottoposto a modifiche o riparazioni. Essa può essere a sua volta
suddivisa in inexpensive maintainance (manutenzione economica ma lenta) e in fast
maintainance (manutanzione rapida ma costosa).
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
28
3. Availability: l’ availability è la probabilità che un sistema sia disponibile in un
determinato istante t. Si definisce dunque un sistema available in un istante t se
esso può fornire un servizio corretto in quel determinato istante.
4. Safety: la safety è la probabilità che in un intervallo di tempo finito non si
presentino condizioni di funzionamento del sistema che possano provocare danni
gravi a persone o cose; in altre parole è la probabilità che non si presentino guasti
catastrofici. E’ chiaro che il concetto di guasto catastrofico è legato alla soggettiva
valutazione dei rischi e dei danni.
1.7 Guasti, errori e malfunzionamenti
Un guasto, fault, è uno stato anomalo dell’hardware e/o del software del sistema che è
conseguenza di un guasto hardware di un componente, di errori di progettazione oppure di
fenomeni quali l’interferenza presente tra due o più sensori.
I guasti e le loro cause possono essere molto diversi; essi vengono classificati secondo la
loro natura (guasti accidentali ed intenzionali), la loro origine (guasti fisici, guasti causati
dall’uomo, guasti interni, guasti esterni, guasti di progetto e guasti operativi) e la loro
persistenza (guasti permanenti e transienti).
Un errore, error, è lo stato corrotto del sistema, conseguenza di un fault temporaneo, che
può portare al fallimento di questo ovvero alla fornitura di un servizio non corretto. Quindi
un errore è causato da un fault cioè da un guasto. In alcuni casi un fault può causare più di
un solo errore. Inoltre un errore può essere latente o rilevato. Un errore si dice latente
(latent error) quando non è stato riconosciuto come tale; un errore, al contrario, può essere
rilevato (detected error) da un algoritmo o meccanismo di rilevamento apposito.
Infine è opportuno definire anche il significato di failure. Un fallimento, failure, è definito
come l’evento in corrispondenza del quale il sistema non fornisce più un servizio corretto
(proper service, ossia un servizio conforme alle specifiche). Quindi avendo definito fault,
error e failure è lecito definire che un guasto è attivato nel momento in cui esso genera un
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
29
errore, mentre si può definire propagazione di un errore il raggiungimento dell’interfaccia
del sistema e la generazione di un malfunzionamento. Si può asserire, quindi, che vi è una
catena che lega i guasti gli errori ed i malfunzionamenti:
1.7.1 Faults nel nodo sensore
Nel lavoro di tesi concentreremo l’attenzione in particolar modo ai guasti nei singoli nodi
sensore dal momento che il tool simula un guasto che potrebbe verificarsi in un generico
sensore di una WSN. I guasti di un sensore possono essere classificati in transienti e
permanenti. I primi sono legati a momentanee condizioni fisiche e si eliminano
definitivamente senza ricorrere ad alcuna procedura di recovery. I guasti transienti
generano soft errors: essi sono errori che si manifestano nella memoria di un calcolatore in
cui avviene una modifica ad un’istruzione di un programma o ad un valore di un dato.
Sebbene un soft error alteri il contenuto di una cella di memoria, esso non è in grado di
danneggiare l’hardware di un sistema a differenza degli hard error. I guasti permanenti,
invece, sono stabili e continui nel tempo. Si provi ad immaginare l’esaurimento di una
batteria di un nodo sensore come un caso di guasto permanente. Studi sperimentali [6]
hanno dimostrato che l’80% dei malfunzionamenti di un sistema informatico sono
provocati da guasti transienti nelle celle di memorie o nei registri del processore. Inoltre i
guasti transienti sono provocati da cause fisiche quali le cadute di tensione, il crosstalk
(disturbo del segnale) e l’urto di particelle cosmiche. L’attenzione deve essere
particolarmente rivolta ai soft errors poiché l’evoluzione della tecnologia elettronica ha
Figura 1.7: Legame tra fault, error e failure
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
30
aumentato la complessità dei circuiti integrati favorendo così la perturbazione di particolari
fenomeni atmosferici che prima venivano considerati ininfluenti. Un tipico
malfunzionamento generato dalla propagazione dei soft errors prende il nome di bit-flip o
anche single-event upset. Il fenomeno del bit-flip è caratterizzato da una temporanea
inversione di un bit. Si verifica uno switch del bit: se il suo valore è 0 allora diventa 1 e
viceversa. Occorre tenere ben presente il concetto di bit-flip perché questo fenomeno è alla
base della tecnica di fault injection adottata dal tool.
E’ importante sottolineare l’assenza di circuiti di ridondanza e di controllo di errore
all’interno del microcontrollore del nodo sensore. Tale scelta è legata ai vincoli di
progettazione del sensore privilegiando la semplicità dell’architettura in modo tale da
ridurre sia il consumo energetico, sia le dimensioni ed anche il costo.
1.8 Valutazione della dependability
La tecnica di valutazione della dependability più interessante per il lavoro di tesi svolto è la
fault forecasting che consente di stimare il numero, la frequenza di incidenza, presente e
futura, e le conseguenze dei guasti. L’obiettivo del fault forecasting è di effettuare una
stima del numero corrente dei fault, stimarne la futura incidenza e le possibili conseguenze.
Vi sono due approcci che possono essere intrapresi: approccio deterministico ed approccio
probabilistico. Il primo ha lo scopo di capire gli effetti dei guasti sul malfunzionamento del
sistema. Il secondo, essendo aleatorio, verte a stimare i parametri della dependability. Una
stima quantitativa del grado di dependability di un sistema può essere ottenuta calcolando
alcuni parametri sintetici tra cui quelli riportati e descritti nella seguente tabella:
Parametro Acronimo Descrizione
Mean Time To Crash MTTC Tempo medio per avere un crash del sistema
Mean Time Between Crashes MTBC Tempo medio tra due crash successivi del
sistema
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
31
Mean Time To Failure MTTF Tempo medio per il verificarsi di un failure
Mean Time Between Failure MTBF Tempo medio tra due failure successivi
Mean Number of Instruction to
Restart
MNIR Numero medio di istruzioni per il ripristino
del sistema
Mean Time To Repair MTTR Tempo medio necessario a riparare il
sistema
Mean Down Time MDT Tempo medio in cui il sistema non è
funzionante
Mean Time Between Errors MTBE Tempo medio tra due errori successivi
In fase di progettazione, design phase, lo studio dell’affidabilità del sistema può essere
condotto utilizzando un software di simulazione: il sistema è sottoposto a situazioni di
errore (simulated fault-injection) con il duplice obiettivo di individuare eventuali
dependability bottlenecks e di stimare la coverage dei meccanismi di fault tolerance. I
feedback derivanti dallo studio delle reazioni del sistema risultano particolarmente utili ai
progettisti ai fini di un miglioramento del sistema.
E’ possibile valutare la dependability analizzando il comportamento di un sistema in
risposta a contesti reali: un approccio di questo tipo, noto come field failure data analysis
(FDDA), consente di ottenere informazioni relative esclusivamente agli errori rilevati
durante il periodo di osservazione e la caratterizzazione statistica che se ne può dedurre.
L’analisi della dependability di un sistema basata su un approccio di tipo measurement-
based si articola in quattro fasi successive: elaborazione dei dati, identificazione del
modello e stima dei parametri, soluzione del modello, analisi del modello e misure.
Tabella 1.1: Parametri per valutare la dependability
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
32
Capitolo 2
Fault injection
La tecnica della fault injection è spesso adoperata per tracciare una stima della
dependability di un sistema.
La fault injection si presta ad essere molto utile per testare l’efficienza dei meccanismi di
fault tolerance ma soprattutto il grado di dependability del sistema. Con l’ausilio di un
simulatore è possibile iniettare particolari guasti, raccogliendo le informazioni sui loro
effetti. Inoltre la fault injection è adoperata per testare la fault detection, la fault isolation e
le capacità di recovery del sistema.
In particolare la fault detection mira a scoprire un guasto sia a livello hardware che a
livello software. Le tecniche di fault detection solitamente comunicano all’utente la
necessità di operare mediante interventi manuali oppure l’inizio di una procedura di
ripristino automatico.
La fault isolation, invece, mira a determinare la causa di un problema generato da un
guasto. Tale tecnica è anche nota col termine fault diagnosis sia a livello hardware che a
livello software.
Spesso si tende ad usare i termini fault isolation e fault detection come sinonimi ma ciò
non è corretto. Fault detection si usa quando si è verificato un problema ed è stato rilevato;
mentre fault isolation quando si individua la causa precisa del guasto e la sua locazione
(senza correggerlo).
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
33
2.1 Tecniche di fault injection
La fault injection può essere realizzata seguendo due livelli di astrazione: a livello
hardware, utilizzando un hardware aggiuntivo (injector); a livello software attraverso degli
strumenti software. La scelta del livello di astrazione da adottare per eseguire la fault
injection è legata allo scopo che si vuole raggiungere. Se si è interessati ad esempio ad un
guasto di tipo stuck-at-faults, è preferibile un’iniezione di tipo hardware potendo così
controllare direttamente la locazione del fault.
I guasti di tipo stuck-at-faults hanno la caratteristica di forzare un valore in modo
permanente in un punto del circuito che può essere rappresentato o da un segnale oppure
da un registro.
La scelta di non usare metodi software di fault injection per fault permanenti nasce dal
fatto che l’esecuzione dell’iniezione non sarebbe molto pratica. Al contrario, se si vuole
alterare un dato, la tecnica software viene in aiuto. Infatti alcuni faults come i bit-flip nelle
celle di memoria possono essere realizzati sia mediante tecniche software che hardware.
Si analizza ora nei dettagli la tecnica hardware di fault injection.
2.1.1 Hardware-Implemented fault injection
La tecnica di Hardware-Implemented fault injection o brevemente denominata HWIFI
viene adoperata per effettuare l’iniezione di faults nell’hardware di un sistema ed
esaminarne gli effetti. Solitamente l’hardware su cui si effettua l’iniezione è costituito da
circuiti VLSI (Very Large Scale Integration) e si tratta di iniezione a livello transistor.
La tecnica HWIFI è utile per testare un circuito dopo che è stato realizzato e verificarne il
suo corretto funzionamento; il circuito viene collegato ad un apparecchio che esegue il
testing su di esso; dopo che è stato iniettato il guasto, viene esaminato il suo
comportamento e si verifica se è corretto (conforme alle specifiche). La procedura descritta
può richiedere del tempo, tuttavia il tempo richiesto per il testing è di gran lunga inferiore a
quello necessario per una simulazione.
Ma la fault injection a livello hardware presenta dei limiti:
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
34
• accessibilità limitata a livello pin: i fault injectors (gli iniettori di guasti)
hardware non possono iniettare guasti nei registri e nella cache.
• costo implementativo extra: per facilitare la fault injection hardware è
richiesto un hardware dedicato per l’iniezione.
2.1.2 Software-Implemented fault injection
La tecnica di fault injection implementata a livello software, più comunemente nota con
l’acronimo SWIFI (Software Implemented Fault Injection), fa uso di appositi strumenti
software per realizzare un’iniezione.
La scelta di questa tecnica spesso risulta vantaggiosa quando non è possibile utilizzare
quella hardware per testare applicazioni e sistemi operativi. Inoltre la tecnica SWIFI non
richiede alcun hardware dedicato e pertanto è conveniente.
I fault injectors SWIFI, dunque, offrono una maggiore flessibilità e semplicità
nell’implementazione della fault injection. L’obiettivo delle tecniche SWIFI è modificare
lo stato hardware/software del sistema attraverso un controllo software che forza il sistema
a comportarsi come se fosse in presenza di un guasto hardware.
Sebbene le tecniche SWIFI siano vantaggiose rispetto alle tecniche HWIFI, esse
presentano alcune problematiche:
• Problema di portabilità
Il carico di lavoro per la migrazione verso nuovi sistemi è abbastanza
oneroso. Il costo per implementare un modello di guasto molto semplice è alto
poiché il programmatore deve scrivere del codice aggiuntivo sia per
coordinare l’esperimento eseguito sui nuovi sistemi, e sia per riportare i
risultati ottenuti.
• Problema del riuso dei componenti
Un componente non è riusabile. Vi è incompatibilità tra componenti di tool
diversi.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
35
• Scarsa flessibilità del metodo di iniezione
Dal momento che nessun tool supporta modelli di guasto molteplici, è
necessario utilizzare un nuovo tool ogni volta che si vuole usare un nuovo
modello di guasto. Diventa quindi poco pratico dover adattare tanti tool, uno
per ogni modello di guasto, a nuovi sistemi. Inoltre ogni tool possiede la
propria interfaccia per configurare gli esperimenti e quindi anche se i tool
venissero usati senza necessità di adattamenti dai nuovi sistemi, ci sarebbe
comunque da considerare un tempo aggiuntivo necessario per il loro
apprendimento.
2.1.3 Fault injection a tempo di compilazione e a tempo di esecuzione
La fault injection a tempo di compilazione inietta faults modificando il codice sorgente del
programma per emulare gli effetti dei guasti hardware, software e transienti.
Un primo metodo è chiamato code mutation che altera le linee del codice che contengono i
faults. Vediamo un esempio semplice di questa tecnica:
Prima: a = a + 1
Dopo: a = a - 1
Un secondo metodo vicino alla code mutation è la code insertion che a differenza del
primo non modifica ma aggiunge codice, attraverso l’utilizzo di una funzione perturbatrice.
Si tratta di una semplice funzione che prende un valore e lo perturba trasformandolo in un
altro valore. Il codice seguente è un semplice esempio che mette in mostra la tecnica
descritta:
int pFunc(int value) {
return value + 20;
}
int main(int argc, char * argv[]) {
int a = pFunc(aFunction(atoi(argv[1])));
if (a > 20) {
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
36
/* do something */
} else {
/* do something else */
}
}
In questo caso pFunc è la funzione perturbatrice che influisce sul valore di ritorno value ed
introduce il fault nel sistema.
La tecnica di compile-time injection non consente però l’iniezione di guasti in modo
interattivo quando cioè il programma è in esecuzione.
Le tecniche di run-time injection fanno uso di trigger software per iniettare un guasto in un
applicativo di sistema in esecuzione. Questi trigger software possono essere implementati
in diversi modi: time-based (quando in un determinato istante viene generata
un’interruzione che consente l’iniezione del guasto); interrupt-based (si adoperano
eccezioni hardware e meccanismi di trap software per generare interruzioni in un punto
specifico del codice o per un particolare evento del sistema come ad esempio l’accesso ad
una specifica locazione di memoria).
Le tecniche di run-time injection possono utilizzare differenti tecniche per l’iniezione di
guasti in un sistema:
• Corruzione dello spazio di memoria: questa tecnica consiste nella
corruzione della RAM, dei registri del processore e della memory-mapped
I/O.
• Tecniche di corruzione delle system calls: il fault si propaga dalle interfacce
del kernel del sistema operativo al software in esecuzione nel sistema.
Vengono intercettare le system calls del sistema operativo fatte dal software a
livello utente e si iniettano i guasti in queste.
• Fault injection a livello rete: questa tecnica è legata alla corruzione, perdita
o riordinamento dei pacchetti di rete.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
37
2.1.4 Fault injection a livello assembly
Iniettare dei guasti a livello assembly può rivelarsi una buona scelta per creare dei SEU
(Single-Event-Upset) e studiarne le conseguenze sul sistema, inoltre è una buona tecnica
anche per valutare l’affidabilità di sistemi operativi differenti.
I SEU sono dei cambiamenti di stato dei dispositivi microelettronici, causati da fenomeni
fisici.
La tecnica della fault injection a livello assembly, a differenza di quella SWIFI, opera ad
un livello di astrazione più basso e pertanto presenta un notevole vantaggio: è possibile
operare sul singolo bit di un registro, sporcando il valore in esso contenuto. Inoltre
l’iniezione viene eseguita con maggior precisione e il programmatore conosce esattamente
il punto di iniezione (la locazione) in modo da poter prevedere le conseguenze del fault
iniettato.
Bisogna però prestare attenzione per utilizzare al meglio questa tecnica. Infatti il tipico
utilizzo dell’injection a livello assembly prevede una scelta casuale del punto di iniezione.
Ma così facendo si rischia di rendere la tecnica poco proficua in quanto molti dei fault
iniettati potrebbero non essere mai attivati: si pensi all’iniezione di un valore errato in un
registro prima che questo venga scritto dall’istruzione successiva oppure all’iniezione di un
fault in un’area di memoria che non verrà mai utilizzata.
2.2 Descrizione della tecnica SWIFI utilizzata e modifiche apportate
Di seguito, inizialmente descriviamo la tecnica SWIFI che è stata introdotta da Aiello nel
suo lavoro di tesi [7] e poi utilizzata da Testa nella versione 1.0 dell’AVR-INJECTION
Tool [9]; successivamente presentiamo le modifiche apportate nella versione 2.0
dell’AVR-INJECTION Tool.
2.2.1 Descrizione della tecnica di injection
Il modello dei fault adottato è del singolo bit-flip noto anche come Single Event Upset
(SEU). Tali fault possono essere iniettati nei registri del processore, nella memoria dati e
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
38
nell’area codice tramite l’utilizzo di istruzioni assembly. Si utilizza inoltre la tecnica di
inserzione del codice, aggiungendo delle istruzioni al programma che richiamano la fault
injection prima di eseguire particolari istruzioni.
Si parte innanzitutto dall’analisi del sistema fault free che consiste nello studio del sistema
originario, cioè la golden copy. Questo studio è fondamentale per la pre-injection ovvero la
fase di conoscenza del flusso di esecuzione e delle risorse utilizzate dal sistema evitando
così l’iniezione di guasti che non verranno mai attivati.
Per settare un esperimento occorre fornire informazioni sul cosa, dove e quando iniettare i
guasti. Il cosa è rappresentato dai SEU (ovvero i bit-flip). Per dove s’intende o la memoria
dati o l’area codice oppure i registri del microcontrollore (su cui si sta applicando la fault
injection). Immaginando che l’istruzione target (istruzione in cui iniettare il fault) sia
eseguita n volte, per quando si intende l’istante in cui viene applicata l’iniezione,
precisamente una tra le n esecuzioni dell’istruzione stessa.
E’ stata scelta la tecnica di inserzione del codice poiché, diversamente dal metodo di
modifica del codice, essa realizza la fault injection durante l’esecuzione del programma
aggiungendo nuove istruzioni invece di modificare quelle esistenti. Il codice creato per fare
fault injection, a differenza di quello della golden copy, presenta dopo l’istruzione di uscita
(<exit>) tre blocchi di codice assembler chiamati: CheckInjection, Injection e
InstructionTarget. Il blocco CheckInjection consente di poter controllare l’istante di
iniezione di un guasto, infatti attraverso un’istruzione di confronto, si verifica se è stato
raggiunto o meno tale istante; in caso affermativo si effettua un salto al blocco di Injection.
Il blocco Injection contiene le istruzioni per effettuare l’iniezione vera e propria. In questo
blocco interviene il registro maschera realizzato per sporcare un particolare bit mediante
un’operazione di xor con il registro vittima dell’iniezione. Conclusa l’iniezione si ritorna al
blocco CheckInjection il quale dopo aver concluso le proprie operazioni effettua un salto al
blocco InstructionTarget. Questo blocco svolge un ruolo di collegamento tra l’esecuzione
dell’applicazione e l’esecuzione dell’iniezione; consente il salto al blocco CheckInjection
e, conclusa l’iniezione, garantisce il proseguimento dell’esecuzione dell’applicazione
affetta dal fault.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
39
2.2.2 Guasti
I fault prodotti dalle procedure sono stati divisi in base al loro punto di iniezione:
• Memoria dati
• Codice
• Registri del processore
2.2.3 Guasti in memoria dati
Per quanto riguarda la memoria, l’idea è stata quella di alterare il valore di una locazione
nell’area dati statica prima che essa venga letta da un’istruzione target. Un esempio pratico
può essere utile per fissare le idee. Si pensi ad un’istruzione target in cui iniettare il fault
come una lds (istruzione di load) che carica un valore contenuto nell’area dati statica in
uno dei registri del microcontrollore (es. r24). Ad esempio considerando l’istruzione target
lds r24, 0x0130 il codice per l’injection sarà il seguente:
lds r24, 0x0130 ; load diretto dallo spazio dati (istr. target)
push r16 ; push nello stack
ldi r16,0x20 ; load immediato nel registro
eor r24,r16 ; xor tra registri
sts 0x0130, r24 ; store diretto verso lo spazio d ati
pop r16 ; pop dallo stack
Si effettua il push di r16 per non sovrascrivere il valore originale dal momento che questo
registro è utilizzato come maschera. Si esegue la xor logica tra la maschera e il valore letto
dalla memoria simulando così il guasto di tipo bit-flip e successivamente in memoria si
memorizza mediante l’operazione di store il valore sporcato.
Un altro caso di guasto in memoria è l’alterazione dell’area dati relativa allo stack in
quanto l’area dati è suddivisa in due porzioni: area dati ottenuti dall’applicazione e area
stack. A tal proposito si riporta un esempio di una procedura assembler per l’injection:
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
40
pop r28 ; pop dallo stack (istruzione target)
push r16 ; push nello stack
ldi r16,0x02 ; load immediato nel registro
eor r28,r16 ; xor tra registri
pop r16 ; pop dallo stack, ripristino valore prec edente del r16
push r28 ; push nello stack del valore sporcato
Tale procedura sostituisce l’istruzione pop r28 leggendo il valore memorizzato nello stack,
sporcandolo mediante un’operazione di xor e inserendo il nuovo valore nello stack.
2.2.4 Guasti nel codice
Sono stati presi in analisi solo fault relativi agli operandi evitando di modificare il codice
operativo dal momento che esiste un’opportuna routine del processore per gestire
l’eccezione sollevata. Un esempio di procedura di injection nel caso di guasto nel codice è
la seguente:
ldi r24, 0x05; load immediato nel registro
push r16 ; push dallo stack
ldi r16,0x20 ; load immediato nel registro
eor r24,r16 ; xor tra registri
pop r16 ; ripristino del valore precedente nel re gistro r16
La procedura mostrata nell’esempio altera il valore dell’operando immediato caricato nel
registro r24.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
41
2.2.5 Guasti nei registri del processore
L’ultimo gruppo di faults è riservato alla modifica dei valori presenti nei registri del
processore soffermando l’attenzione sul registro Program Counter (PC) e sul registro
Status Register (SR).
Per realizzare un guasto nel Program Counter è sufficiente realizzare un injector che
contenga una semplice istruzione di salto incondizionato come jmp, rjmp, ijmp, ed ejmp.
Vediamo un esempio:
jmp 0x1a9c ;indirizzo istruzione target con il 5 bi t modificato
Per quanto riguarda lo Status Register, è sufficiente utilizzare una delle istruzioni
disponibili per modificare i flag dello status register e cioè: bset k e bclr k che settano
rispettivamente ad 1 e a 0 il k-esimo bit del registro di stato oppure sec, clc, sen, cln, sez,
clz, sei, cli, ses, cls, sev, clv, set, clt, seh e clh che settano i flag dello Status Register.
2.2.6 Tecnica per la rilevazione dell’istante di injection
Individuata la procedura di injection, occorre stabilire quando essa deve essere invocata dal
momento che potrebbe essere eseguita più volte all’interno di un programma target. Inoltre
è difficile che lo stesso SEU si presenti più volte nel corso di una sola esecuzione del
programma target.
Il diagramma di flusso in figura 2.1 illustra il principio della tecnica. Occorre concentrarsi
sulla logica del rombo presente nel diagramma di flusso riportato. Tale logica è stata
definita mediante la seguente procedura assembly che aggiunge al codice dell’applicazione
un overhead trascurabile:
push r16 ; salvataggio nello stack del valore del r egistro r16
in r16,sreg ; lettura dello status register
push r16 ; salvataggio status register nello stac k
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
42
lds r16,0x0131
cpi r16,0x55 ; confronto del valore letto con l’ immediato 0x55
breq .+72 ; salta, se il valore immediato `e pres ente in r16
lds r16,0x0EC1;
cpi r16,0x55 ; confronto del valore letto con l’ immediato 0x55
breq .+66 ; salta, se il valore immediato `e pres ente in r16
lds r16,0x0CC1
cpi r16,0x55 ; confronto del valore letto con l’ immediato 0x55
breq .+60 ; salta, se il valore immediato `e pres ente in r16
lds r16,0x0132 ; load del valore di avvenuto init del conteggio
cpi r16,0x55 ; confronto del valore letto con l’ immediato 0x55
breq .+16 ; salta, se il valore immediato `e pres ente nel r16
ldi r16,0x55 ; load immediato 0x55 nel registro r 16
sts 0x0132,r16 ; store del valore 0x55 nella memo ria
ldi r16,0x03 ; inizializza il contatore con il nu mero di cicli
sts 0x0133,r16 ; store del valore del contatore
jmp 0x2382 ;
lds r16,0x0133 ; load del valore del contatore
dec r16 ; decrementa il contatore
sts 0x0133,r16 ; aggiorna il valore del contatore
tst r16 ; verifica se il contatore è arrivato a z ero
brne .+18 ; salta, se il valore immediato non è p resente nel r16
ldi r16,0x55 ; load immediato 0x55 nel registro r 16
sts 0x0131,r16 ; store del valore 0x55 nella memo ria
sts 0x0CC1,r16; store del valore 0x55 nella memor ia
sts 0x0EC1,r16; store del valore 0x55 nella memor ia
jmp 0x238A ; invocazione della procedura di injec tion
pop r16 ; lettura dallo stack del vecchio status register
out sreg,r16 ; ripristino del valore dello status register
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
43
pop r16 ; ripristino del valore iniziale del regi stro r16
In tale procedura inizialmente avviene il salvataggio del valore dello Status Register in
modo da conservare il suo valore durante l’esecuzione della procedura di controllo; poi si
effettua un controllo in memoria per verificare se l’injection è stata già effettuata ed il
controllo, per aumentare l’affidabilità, viene ripetuto in altre locazioni non contigue
(0x0131,0x0CC1 e 0x0EC1), diminuendo così la probabilità di sporcare l’area di memoria
utilizzata per il controllo.
Vi è inoltre un controllo del ciclo in cui iniettare un guasto, la prima volta che la procedura
è richiamata si verifica l’inizializzazione del contatore di cicli inserendo il valore del
contatore di ciclo nella locazione 0x0133. Se l’iniezione non è stata ancora effettuata si
decrementa il valore del contatore e quando si raggiunge il valore zero si fa la chiamata
alla procedura di injection (effettuando la vera e propria iniezione).
Main Program
Instruction Target
Inj.?
Injection Block
YES
NO
Figura 2.1: Procedura per l’individuazione dell’istante di injection
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
44
Tale tecnica si rivela molto utile poiché è possibile specificare l’istante in cui effettuare
l’iniezione e si evita che qualche malfunzionamento modifichi il valore di avvenuta
injection (sfruttando la presenza ridondante di tale valore in tre locazioni non contigue).
2.2.7 Modifiche apportate
Un primo problema riscontrato nella tecnica di injection, utilizzata nella versione 1.0
dell’AVR-INJECT Tool realizzato da Testa nel suo lavoro di tesi [9], consiste nella scelta
statica delle locazioni di memoria in cui salvare le informazioni di controllo. In particolare
questa scelta non si addice alla caratteristica di generalità del tool, infatti al variare
dell’applicazione varia il codice e di conseguenze le locazioni scelte potrebbero coincidere
con locazioni richiamate dall’applicazione stessa provocando dei conflitti. Per risolvere
questo problema è stato modificato il tool, in questo modo ogni volta che viene caricata
una nuova applicazione le locazioni necessarie a contenere le informazioni di controllo
sono scelte dinamicamente, ed in modo casuale, tra quelle che non sono mai utilizzate
dall’applicazione stessa.
Un altro problema è stato riscontrato nella tecnica per l’individuazione dell’istante di
injection, infatti quando viene inizializzato il registro contatore (e cioè la prima volta che
viene eseguita l’istruzione target) esso non viene decrementato, questo comporta che
l’iniezione viene effettuata con un ciclo di ritardo; ad esempio se l’utente volesse
effettuare l’iniezione durante la prima esecuzione dell’istruzione target l’iniezione vera e
propria avverrebbe luogo solo durante la seconda esecuzione dell’istruzione target. Per
risolvere questo problema il registro contatore è stato inizializzato con il valore di ciclo già
decrementato ed è stato inserito un controllo aggiuntivo per la verifica del raggiungimento
dell’istante di injection. Riportiamo di seguito la procedura per l’individuazione
dell’istante di injection modificata:
push r16
in r16, sreg
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
45
push r16 ; Saving SR
lds r16, loc1
cpi r16, 0x55
breq .+76 ; ->Exit
lds r16, loc2
cpi r16, 0x55
breq .+68 ; ->Exit
lds r16, loc3
cpi r16, 0x55
breq .+60 ; ->Exit
lds r16, loc4
cpi r16, 0x55
breq .+20 ; ->Exit
ldi r16, 0x55
sts loc4, r16
ldi r16, val; ->Initialize the counter with the n umber of cycles
sts loc5, r16
tst r16
breq .+18 ; ->Ciclo Injection
jmp loc_exit ; -> Exit
lds r16, loc5 ; -> Verify count
dec r16
sts loc5, r16 ; -> Update the value of the counte r
tst r16
brne .+18 ; ->Exit
ldi r16, 0x55
sts loc1, r16
sts loc2, r16
sts loc3, r16
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
46
call loc_injection ; ->Injection
pop r16 ; -> Exit
out sreg, r16 ; -> Recovery SR
pop r16
ret
Dove abbiamo indicato con loc1, loc2, loc3, loc4 e loc5 le locazioni calcolate
dinamicamente dal tool ; con val il valore del ciclo di iniezione scelto dall’utente; con
loc_exit la locazione in cui si effettua il ripristino dello status register e con loc_injection
la prima locazione del blocco Injection.
Un altro errore riscontrato nel meccanismo di iniezione è relativo al calcolo automatico
delle locazioni, infatti sia per l’istruzione target che per quella successiva è sempre
considerata un’occupazione di memoria pari a due byte; tuttavia nell’instruction set del
microcontrollore AVR ATMega128L (microprocessore del sensore wireless mica2) sono
presenti anche istruzioni a quattro byte. Per risolvere questo problema è bastato fare un
controllo sul codice operativo delle istruzioni, discriminando quelle di quattro byte dalle
altre di due byte, durante il calcolo automatico delle locazioni.
Un ulteriore problema affrontato è stato quello delle istruzioni non idempotenti (ad
esempio l’istruzione add). In particolare, nella versione precedente, l’istruzione target
(quella in cui si vuole effettuare l’iniezione) è eseguita sia all’interno del blocco
InstructionTarget che nel blocco di Injection, provocando inevitabilmente problemi con le
istruzioni che per loro natura non sono idempotenti. Per risolvere questo problema si sono
modificati i blocchi di Injection e di InstructionTarget per le istruzioni non idempotenti;
più precisamente nel blocco di Injection non è più eseguita l’istruzione target ma avviene
solo la modifica del suo operando (attraverso l’operazione di xor) mentre nel blocco di
InstructionTarget l’esecuzione dell’istruzione target è stata posticipata rispetto alla
chiamata della procedura CheckInjection. Per chiarire ulteriormente il meccanismo, di
seguito riportiamo le sezioni di Injection e InstructionTarget relative ad un’istruzione
target non idempotente:
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
47
<Injection>:
push r16
ldi r16, 0x1 ; -> Loading mask
eor r24,r16 ; -> Register with bit-flip
pop r16
ret ;-> Return to CheckInjection
<InstructionTarget>:
call loc_CheckInj ; -> Jump to CheckInjection
subi r24,0x74 ; -> Instruction to be flipped
sbci r25, 0xFF ; -> Next instruction
jmp loc_main_program; -> Return to main program
Un’ulteriore modifica apportata alla tecnica di injection è quella relativa all’iniezione dei
faults nel registro di stato (Status Register), in particolare nella versione precedente
l’iniezione del guasto avveniva azzerando semplicemente uno dei bit del registro di stato;
tuttavia qualora il valore del bit scelto fosse già zero allora l’iniezione non sarebbe stata
effettuata. Per risolvere questo tipo di problema abbiamo modificato i blocchi di
InstructionTarget ed Injection in modo tale da cambiare opportunamente il valore del bit
del registro di stato selezionato dall’utente. Di seguito riportiamo le sezioni modificate:
<Injection>:
push r16
ldi r16, 0x1 ; -> Loading mask
eor r28, r16 ; -> Register with bit-flip
pop r16
ret ;-> CheckInjection
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
48
<InstructionTarget>:
push r28
in r28, sreg
call loc_CeckInj ; -> Jump to CheckIn jection
out sreg, r28 ; -> Recovery SR
pop r28
adc r25,r25 ; -> Instruction to be flipped
add r24, r18 ;-> Next instruction
jmp loc_main_program
In particolare dalla sezione InstructionTarget si vede come in primo luogo viene salvato
nello stack il contenuto del registro r28, il quale verrà utilizzato come registro di appoggio
per salvare il contenuto del registro di stato; si effettua poi il salto alla sezione
CheckInjection per verificare se è stato raggiunto il ciclo in cui iniettare il fault ed in caso
affermativo viene modificato il bit del registro r28. Quindi quando dalla sezione
CheckInjection si ritorna alla sezione InstructionTarget viene caricato nel registro di stato
il contenuto del registro r28 (tale contenuto è stato modificato solo se è stata effettuata
l’iniezione del fault), viene ripristinato il valore originario del registro r28 e viene eseguita
l’istruzione target (è da notare che, in caso di iniezione del fault, viene modificato il
contenuto del registro di stato prima dell’esecuzione dell’istruzione target in quanto tale
istruzione utilizza il valore di un particolare bit del registro di stato).
Infine rispetto alla versione precedente è stata ampliata la tipologia dei fault relativi ai
registri del processore, infatti oltre ai fault nel PC e nel registro di stato sono stati
introdotti i fault nello stack pointer (registro SP).
Riportiamo di seguito le sezioni di Injection e InstructionTarget relative a questa
particolare tipologia di faults:
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
49
<Injection>:
push r16
ldi r16, 0x1 ; -> Loading mask
eor r28, r16 ; -> Register with bit-flip
pop r16
ret ;-> CheckInjection
<InstructionTarget>:
push r16
push r28
in r28, spl
call loc_CheckInj ; -> Jump to CheckInje ction
lds r16, loc1
cpi r16, 0x55
brne .+20 ; ->Recovery SP
mov r16, r28
pop r28
sts loc1, r28
mov r28, r16
pop r16
out spl, r28 ; -> Modify SP
lds r28, loc1
rjmp .+4
pop r28
pop r16
push r28 ; -> Instruction to be flipped
push r29 ;-> Next instruction
jmp loc_main_program
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
50
Dalla sezione InstructionTarget si nota come in primo luogo vengono salvati nello stack i
valori dei registri r28 ed r16 che sono successivamente utilizzati come registri di
appoggio, infatti nel registro r28 viene salvato il contenuto del registro SP (dato che il
registro SP è a 16 bit è l’utente che decide se modificare un bit della parte alta o della parte
bassa del registro; nell’esempio l’utente ha deciso di modificare la parte bassa) mentre il
registro r16 è utile per verificare se è stata effettuata o meno l’iniezione del fault . In
particolare se l’esecuzione corrente non è quella relativa al ciclo di iniezione del fault
(quindi il registro SP non ha subito modifiche), dopo aver effettuato la chiamata alla
sezione CheckInjection, vengono semplicemente ripristinati i valori originari dei registri
r28 ed r16 prima di eseguire l’istruzione target e l’istruzione successiva. Se invece il ciclo
di esecuzione corrente è quello relativo all’iniezione del fault, allora oltre a ripristinare i
valori originari dei registri r28 ed r16, viene caricato nel registro SP il valore ottenuto in
seguito all’iniezione del fault prima di eseguire l’istruzione target e subito dopo quella
successiva.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
51
Capitolo 3
AVR-INJECT Tool versione 2.0: la progettazione
In questo capitolo si descrive la progettazione della versione 2.0 del tool AVR-INJECT.
Pertanto sono mostrati alcuni use cases, un component diagram, un class diagram e
qualche sequence diagram. In particolare iniziamo evidenziando le differenze tra la
versione attuale e la versione precedente del tool.
3.1 AVR-INJECT Tool
Di seguito riportiamo il grafico che schematizza le fasi del tool mettendo in evidenza cosa
è stato aggiunto e che cosa è stato modificato.
Pre-Injection
Codice disassemblato (Golden Copy)
GC Trace GC Profile
Set-up esperimenti
Codice con inserzione (1...n)
Esecuzione
Profile (1..n)
Trace (1..n)
Analisi dei risultati
Input Input (Tabelle,Grafici...)
Figura 3.1: Fasi dell’AVR-INJECT Tool
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
52
Dalla figura 3.1 si nota che la fase di Set-up esperimenti è stata colorata di giallo per
indicare che ha subito modifiche rispetto alla versione precedente del tool mentre la fase di
Analisi dei risultati è stata colorata di verde per indicare che è stata implementata a
partire dalla versione corrente del tool.
Il tool, per il suo funzionamento, utilizza l’emulatore Avrora che permette di emulare una
rete di sensori senza filo i cui nodi sono dei microcontrollori AVR. E’ importante
evidenziare che i file di trace e di profile utilizzati o prodotti nelle varie fasi del tool sono
generati utilizzando gli strumenti messi a disposizione dall’emulatore Avrora.
Il tool permette l’esecuzione sia di singoli esperimenti che di studi di fault injection. In
particolare uno studio è un’insieme di esperimenti, il numero di tali esperimenti dipende
dagli intervalli di variazione del bit-flip e dell’istante di iniezione. Il tool prevede due
tipologie differenti di studio: studio step-by-step in cui l’utente deve specificare il valore
iniziale,quello finale ed il passo (step) sia per l’intervallo di variazione del bit-flip che per
quello dell’istante di iniezione; studio random in cui l’utente specifica il valore
iniziale,quello finale ed il passo (step) per un solo intervallo di variazione (bit-flip o istante
di iniezione) mentre per l’altro questi valori sono generati in modo casuale dal tool.
Durante la fase di Analisi dei risultati il tool oltre a confrontare il file di trace della
Golden Copy con quello degli esperimenti di fault injection interpreta i risultati
effettuando una classificazione. Descriviamo brevemente il meccanismo di classificazione
degli errori, in particolare le tipologie di errori considerate sono quattro: errori latenti ,
crash error, hang error ed errori da approfondire . Dal confronto dei file di trace si può
verificare una delle seguenti condizioni:
1. Nessuna differenza riscontrata: in questo caso per l’esperimento di fault
injection è stato individuato un errore latente.
2. Qualche differenza e presenza di cicli: in questo caso per l’esperimento di fault
injection è stato individuato un hang error.
3. Notevole differenza tra i cicli macchina eseguiti dalla golden copy e quelli
eseguiti dall’esperimento, indipendentemente dalle differenze: in questo caso
per l’esperimento di fault injection è stato individuato un crash error.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
53
4. Nessuna delle condizioni precedenti: in questo caso per l’esperimento di fault
injection è stato individuato un errore da approfondire.
3.2 Casi d’uso nel tool
Per chiarezza riportiamo di seguito il diagramma dei casi d’uso e poi per ognuno una
breve descrizione:
Nella figura 3.2 sono evidenziati i casi d’uso del tool con i relativi rapporti. Dal
diagramma si nota la presenza di un solo attore, l’utente, che è il solo che interagisce con il
sistema. Inoltre il caso d’uso relativo alla creazione di uno studio è stato scisso in due casi
d’uso distinti (step-by-step e random). Rispetto ai casi d’uso della versione precedente del
user
Delete experiment
Delete study
New step-by-stepstudy
New random study
Save project
Run project
Delete projectNew project
Open project
New experiment
View Results
Figura 3.2: Diagramma dei casi d’uso
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
54
tool, è stato inserito il caso d’uso per la visualizzazione dei risultati (View Results) ed è
stato modificato quello relativo all’esecuzione del progetto (Run project).
1. New project
E’ il caso d’uso più importante poiché da esso ha origine tutto il funzionamento
dell’AVR-INJECT tool. Infatti l’utente per poter impostare un esperimento o uno
studio per effettuare la fault injection deve innanzitutto creare un nuovo progetto
che include successivamente un certo numero di esperimenti o di studi. Per la
creazione del nuovo progetto all’utente è richiesto l’inserimento del nome
desiderato attraverso l’interfaccia GUI.
2. New experiment
Caso d’uso che consente l’inserimento di un nuovo esperimento, a cui l’utente può
assegnare un nome qualsiasi. E’ importante notare che questo caso d’uso richiede il
caso d’uso di creazione del progetto. In seguito alla creazione dell’esperimento,
nell’interfaccia GUI appare un nuovo pannello formato dai campi necessari a
contenere le informazioni relative all’esperimento di fault injection che si vuole
effettuare.
3. New step-by-step study
Avviene l’inserimento di un nuovo studio, a cui l’utente può assegnare un nome
qualsiasi. E’ importante notare che anche questo caso d’uso richiede il caso d’uso
di creazione del progetto. In seguito alla creazione dello studio, nell’interfaccia
GUI, appare un nuovo pannello formato dai campi necessari a contenere le
informazioni relative allo studio di fault injection che si vuole effettuare. I
parametri in questo tipo di studio sono tutti deterministici, in particolar modo si
ricorda che i valori del bit-flip e del ciclo d’iniezione sono ricavati attraverso uno
step impostato dall’utente.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
55
4. New random study
Avviene l’inserimento di un nuovo studio, a cui l’utente può assegnare un nome
qualsiasi. E’ importante notare che anche questo caso d’uso richiede il caso d’uso
di creazione del progetto. A differenza del precedente, in questo caso d’uso vi è
un’ulteriore radiobutton nel pannello dell’interfaccia GUI che consente all’utente di
scegliere quale tra il bit-flip e il numero di cicli deve essere generato in automatico
dal sistema.
5. Delete experiment
L’esperimento, dopo essere stato creato e/o avviato, può essere cancellato. Questo
caso d’uso permette all’utente di eliminare un esperimento all’interno di un
progetto. Per cancellare l’esperimento desiderato l’utente prima lo seleziona
all’interno dell’albero dei progetti, presente nell’interfaccia GUI, e poi dopo clicca
sull’apposito pulsante di cancellazione.
6. Delete study
A differenza dell’inserimento, non è più necessaria la distinzione tra studio step-by-
step e studio random. Il caso d’uso in questione prevede la rimozione di uno studio
indipendentemente dal tipo. Anche in questo caso per cancellare un particolare
studio l’utente prima lo seleziona all’interno dell’albero dei progetti, presente
nell’interfaccia GUI, e poi dopo clicca sull’apposito pulsante di cancellazione.
7. Delete project
L’utente può cancellare un progetto che in precedenza aveva realizzato per far
spazio a nuovi progetti con caratteristiche diverse. Anche in questo caso per
cancellare un particolare progetto l’utente prima lo seleziona all’interno dell’albero
dei progetti, presente nell’interfaccia GUI, e poi dopo clicca sull’apposito pulsante
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
56
di cancellazione. In questo caso la cancellazione di un progetto comporta anche la
cancellazione di tutti gli esperimenti e di tutti gli studi in esso contenuti.
8. Run project
E’ uno dei casi d’uso più interessanti nella fase di progettazione del tool. Con
l’ausilio di uno specifico pulsante, si avvia l’esecuzione del progetto selezionato
dall’utente. L’esecuzione consiste nella simulazione di tutti gli esperimenti e studi
presenti al suo interno. Questo caso d’uso è quello che ha subito delle modifiche
rispetto alla versione precedente del tool. Infatti nella versione attuale del tool
l’esecuzione di un progetto non si limita alla generazione di alcuni file per ogni
esperimento, ma realizza anche un’analisi approfondita di tali file. Inoltre,
terminata l’esecuzione, i risultati ottenuti sono visualizzati all’interno del tool
attraverso la creazione di appositi grafici.
9. Open project
Durante la realizzazione del tool, si è pensato che fosse opportuno recuperare
progetti salvati precedentemente per poterli modificare. Il tool gestisce quindi il
recupero di progetti purché essi siano stati precedentemente salvati all’interno del
sistema.
10. Save project
Quando l’utente decide di uscire dall’applicazione, se non è stato fatto un
salvataggio dell’albero dei progetti, tutto il lavoro andrà perso (problema della
persistenza dei dati). Quindi se l’utente desidera continuare la fault injection sui
progetti creati in una sessione successiva deve salvare l’albero dei progetti. A tale
scopo è presente nell’interfaccia GUI un apposito pulsante che serve a salvare le
informazioni dei progetti in un file xml.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
57
11. View Results
L’ultimo caso d’uso da considerare è la visualizzazione dei risultati. I risultati sono
disponibili solo se è stato già eseguito un progetto. I risultati sono riportati in forma
grafica (diagrammi a torta ed istogrammi) e sono associati ai particolari studi
attraverso un nodo Output nell’albero dei progetti.
3.3 Component diagram
Si è scelto appositamente di rappresentare prima il diagramma dei componenti del sistema
e poi il diagramma delle classi. Questo consente di avere principalmente una visione
globale del funzionamento del sistema mettendo a fuoco le dipendenze più evidenti. Nel
prossimo paragrafo si effettua un’analisi più approfondita ed accurata delle classi che
costituiscono il sistema. Per quanto riguarda il component diagram, sono stati individuati
quattro componenti principali (Figura 3.3): la GUI (Graphical User Interface),
l’esperimento, l’iniezione ed infine il parser XML. Di seguito descriviamo brevemente i
componenti:
GUI
Experiment
Injection XML Parser
Figura 3.3: Component diagram
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
58
• GUI
La GUI è stata implementata con l’ausilio delle librerie grafiche che java
mette a disposizione. Attraverso tale componente l’utente può utilizzare il tool
in maniera semplice ed intuitiva; sarà poi compito del tool fornire al sistema
le informazioni specificate dall’utente.
• Injection
Il componente Injection gestisce la vera e propria iniezione del fault. Esso si
occupa di trasformare il file della Golden Copy in un file dello stesso tipo
(ossia un file disassemblato con estensione .od) in cui è inserito anche la
porzione di codice che gestisce la fault injection.
• XML Parser
Questo componente analizza il file xml che il tool genera dinamicamente al
variare dei valori impostati dall’utente. In particolare, dopo che l’utente ha
specificato i valori e li ha confermati (i valori sono riferiti ai parametri che
caratterizzano gli esperimenti o gli studi che costituiscono un progetto), il tool
possiede in un file xml (trasparente all’utente) tutte le informazioni necessarie
per la simulazione. Quando l’utente vuole eseguire un progetto, il tool si serve
di un parser (ovvero analizzatore) che esamina il documento xml prodotto ed
estrae da esso le informazioni utili; queste informazioni sono poi inviate al
componente Experiment. In caso di salvataggio dei progetti, il contenuto del
file xml prodotto dal tool viene copiato interamente in un nuovo file xml; di
questo nuovo file xml l’utente sceglie il percorso di salvataggio ed il nome. Al
contrario, quando l’utente desidera caricare tutti i progetti contenuti in un file
xml, il tool effettua un’operazione inversa trasferendo il contenuto di tale file
nel file xml interno al tool (denominato input.xml) su cui opera il componente
XML Parser.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
59
• Experiment
Il componente Experiment è il componente principale del tool in quanto
gestisce i componenti Injection e XML Parser grazie ai quali può ottenere il
file definitivo che verrà utilizzato dall’emulatore Avrora. Tale componente è
stato progettato per realizzare singoli esperimenti, studi deterministici del tipo
step-by-step e studi aleatori. Inoltre rispetto alla versione precedente del tool,
questo componente ha anche il compito di analizzare, per ogni esperimento
eseguito, i file generati dall’emulatore Avrora e di visualizzare i risultati
ottenuti attraverso la creazione di appositi grafici.
3.4 Class diagram
Rispetto alla versione precedente, nella versione 2.0 dell’AVR-INJECT Tool sono state
introdotte sei nuove classi: AnalisiTrace.java, GenerateValChart.java, CreatePieChart.java,
CreateBarChart.java, CreateBarChartLat.java e MyCellRender.java. In questo paragrafo
descriviamo brevemente le classi che sono state ereditate dalla versione precedente del
tool, mentre analizziamo in modo più dettagliato le nuove classi introdotte.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
60
Nel diagramma di figura 3.4 le classi che hanno subito modifiche rilevanti rispetto alla
versione precedente del tool sono state colorate in giallo mentre quelle che sono state
introdotte nella nuova versione del tool sono state colorate di verde. Inoltre nel diagramma
non sono riportati gli attributi ed i metodi di ciascuna classe per una questione di spazio.
Main.java
E’ la classe principale dell’applicazione. Consente l’avvio del tool creando l’oggetto di
tipo ToolGUI che inizializza i componenti dell’interfaccia grafica.
ToolGUI.java
Realizza e gestisce tutti i componenti grafici necessari per l’impostazione ed esecuzione di
uno o più progetti.
OD
Riga
<<istantiate>><<istantiate>>
Iniezione
Esperimento
ParseXMLFile
«uses»
GenerateValChart
«uses»
CreatePieChart CreateBarChart CreateBarChartLat
«uses» «uses»
ToolGUI
«uses»
«uses»
Tree
«uses»
MyCellRender«uses»
Main
«uses»
ODFilter
«uses»
FilterJarFilterXml
«uses»«uses»
AnalisiTrace
«uses»
1
n<<istantiate>>
1
n
<<istantiate>>
1
n
<<is
tant
iate
>>
<<ist
antia
te>>
<<ist
antia
te>>
Figura 3.4: Class diagram
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
61
Esperimento.java
E’ la classe che si occupa di eseguire le operazioni richieste dalla classe ToolGUI per la
realizzazione della fault injection. Attraverso l’utilizzo di cicli for innestati, la classe
Esperimento prepara i file necessari per l’emulatore Avrora e, grazie ad appositi script,
imposta i comandi da eseguire per la simulazione. Inoltre rispetto alla versione precedente
del tool la classe Esperimento sfrutta le funzionalità di altre classi per analizzare i file
generati dall’emulatore Avrora e generare i grafici dei risultati.
Iniezione.java
E’ la classe che include il vero e proprio motore del tool. Infatti è in questa classe che si
costruisce passo dopo passo il file disassemblato modificato (il file ha estensione .od e
viene modificato in funzione dei parametri immessi dall’utente per l’iniezione del fault)
che serve all’emulatore Avrora per eseguire la simulazione.
ParseXMLFile.java
Per memorizzare i valori inseriti dall’utente, si è pensato di adoperare un file xml che viene
appositamente creato dal tool al suo avvio. La scelta di utilizzare questo tipo di file è nata
dalla semplicità di raccolta ed organizzazione delle informazioni poste su livelli diversi.
Pertanto è necessaria una classe che sia in grado di estrapolare dal file xml le informazioni
richieste conservando allo stesso tempo i loro rapporti di gerarchia.
OD.java
La classe OD (che prende il nome proprio dall’estensione del file che si vuole ottenere) ha
lo scopo di caricare il file .od di partenza (golden copy) e di cui l’utente è in possesso,
modificarlo aggiungendo blocchi di codice per la gestione dell’iniezione (in particolare i
blocchi di CheckInjection, Injection ed InstructionTarget), salvarlo e creare la directory
che conterrà tutti i file di output del tool.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
62
Riga.java
La classe Riga è stata creata per manipolare le righe del codice disassemblato. Mediante
questa classe il tool può estrarre una riga, può modificare la riga di codice corrispondente
al punto di iniezione sostituendo l’istruzione corrente con una chiamata al blocco relativo
all’injection (in particolare il blocco richiamato è InstructionTarget). Spesso il tool ricorre
ad un processo di tokenizzazione della riga: essa viene spezzettata in token i quali vengono
usati per determinati scopi (ad es. per il calcolo del Program Counter nei blocchi di codice
dell’injection).
Tree.java
Per una semplice navigazione tra i progetti, gli studi, gli esperimenti creati dall’utente si
ricorre ad una specifica classe: Tree. Da un punto di vista grafico essa consente di
visualizzare i progetti come tante cartelle che fanno capo ad una cartella radice denominata
Projects. Queste cartelle al loro interno contengono o soli esperimenti o soli studi o
entrambi. Da un punto di vista implementativo possiamo vedere una struttura ad albero
avente come radice il nodo Projects avente i progetti come nodi figli e gli esperimenti e/o
studi come nodi nipoti. Questa classe, rispetto alla versione precedente del tool, ha subito
delle modifiche importanti, in primo luogo è aumentata la profondità dell’albero
aggiungendo dei nodi figli ai nodi esperimento e ai nodi studio per contenere i grafici dei
risultati, ed in secondo luogo è cambiato l’aspetto grafico dei nodi esperimento e nodi
studio facilitando l’identificazione da parte dell’utente. In particolare, grazie all’utilizzo
della classe MyCellRender, è stato possibile associare immagini differenti alle tre tipologie
di nodi ossia agli esperimenti, agli studi step-by-step ed agli studi random, invece in
precedenza tutti i nodi avevano la stessa immagine e quindi risultava difficile da parte
dell’utente identificarli. Infine la classe Tree, per il corretto funzionamento del tool, crea
una corrispondenza biunivoca tra i nodi dell’albero e i nodi del file xml.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
63
ODFilter.java
E’ una classe ausiliaria per la ricerca e la selezione del file disassemblato (con estensione
.od) corrispondente alla golden copy di un’applicazione su cui effettuare la fault injection.
FilterXml.java
E’ una classe ausiliaria utilizzata per il salvataggio o l’apertura di progetti raccolti in un
file xml.
FilterJar.java
E’ una classe ausiliaria utilizzata per la ricerca del file con estensione .jar che permette
l’avvio dell’emulatore Avrora.
AnalisiTrace.java
La classe AnalisiTrace è stata creata per confrontare il file di trace dell’esperimento di
fault injection con quello della golden copy e classificare opportunamente il tipo di errore
individuato. L’output dell’analisi è un file testuale, chiamato Risultati.txt, che oltre al
risultato della classificazione contiene anche delle informazioni utili ricavate durante il
confronto; per chiarezza riportiamo di seguito il contenuto del file relativo ad un
esperimento di fault injection:
Si tratta di un hang error
Il TTH è: 14353
L'ampiezza del ciclo è: 27
La latenza del fault è di: 88
Il numero di disallineamenti è: 353431
Il numero di confronti è: 353443
Il numero di allineamenti a buon fine è: 0
Il numero di cicli identificati è maggiore di 2000
Tutte le problematiche affrontate in questa fase saranno presentate in modo dettagliato nel
paragrafo finale del capitolo.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
64
GenerateValChart.java
La classe GenerateValChart è stata creata per ottenere i valori in base ai quali costruire i
grafici dei risultati. E’ opportuno specificare che nel caso di un singolo esperimento non
viene generato nessun grafico ma sono riportate all’interno del tool solo le informazioni
contenute nel file Risultati.txt, la generazione dei grafici avviene solo in corrispondenza di
studi. Descriviamo brevemente il meccanismo per il calcolo dei valori con cui costruire i
grafici. La classe, tiene traccia del numero di errori di ciascuna categoria attraverso
l’utilizzo di appositi contatori che sono aggiornati al termine dell’esecuzione di ogni
esperimento di uno studio e subito dopo che è terminata la fase di analisi dei file di trace .
Quando poi sono stati eseguiti tutti gli esperimenti di uno studio, è possibile calcolare le
percentuali di occorrenza delle varie tipologie di errori e con questi valori realizzare i
grafici di interesse.
CreatePieChart.java
Questa classe, come si capisce già dal nome, ci permette di creare il grafico a torta che
mostra le percentuali di occorrenza delle quattro tipologie di errori nello studio di fault
injection. Per la realizzazione del grafico e la sua personalizzazione sono stati sfruttati i
metodi messi a disposizione dalla libreria grafica JFreeChart.
CreateBarChart.java
Questa classe, come si capisce già dal nome, ci permette di creare degli istogrammi dei
risultati di uno studio di fault injection. In particolare sono creati due tipi di istogrammi,
uno che mostra le percentuali di occorrenza delle quattro tipologie di errori al variare del
ciclo di iniezione e l’altro che mostra le percentuali di occorrenza delle quattro tipologie di
errori al variare del bit-flip. Per la realizzazione degli istogrammi e la loro
personalizzazione sono stati sfruttati i metodi messi a disposizione dalla libreria grafica
JFreeChart.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
65
CreateBarChartLat.java
Questa classe, come si capisce già dal nome, è simile alla classe precedente e ci permette
la realizzazione di un istogramma. La differenza sostanziale con la classe precedente sta
nel tipo di istogramma realizzato, infatti in questa classe viene creato l’istogramma della
latenza. In questo istogramma sono presi in considerazione solo gli errori di tipo crash e di
tipo hang e sono riportate le loro percentuali rispetto ai cicli di latenza riscontrati. E’ bene
ricordare che la latenza è definita come il numero di cicli che intercorrono dal momento in
cui si attiva l’iniezione (si verifica l’istante di iniezione) fino al momento in cui l’iniezione
agisce effettivamente sul sistema (provocando un crash error o un hang error). Anche in
questo caso, per la realizzazione dell’istogramma della latenza e la sua personalizzazione
sono stati sfruttati i metodi messi a disposizione dalla libreria grafica JFreeChart.
MyCellRender.java
Questa classe è stata realizzata per modificare a livello grafico l’albero dei progetti
presenti nel tool, in modo tale che l’utente possa distinguere tra esperimenti, studi step-by-
step e studi random, semplicemente guardando l’albero. In particolare questa classe
associa ai nodi esperimenti, ai nodi studio step-by-step ed ai nodi studio random delle
icone differenti.
3.5 Sequence diagram
Per brevità, in questo paragrafo, non si riportano i sequence diagram di tutti gli scenari del
tool ma solamente quelli di maggior interesse ai fini della sua comprensione e quelli che
hanno subito variazioni rispetto alla versione precedente del tool.
3.5.1 Sequence diagram n°1: nuovo esperimento
Si vuole illustrare lo scenario che realizza l’inserimento di un nuovo esperimento in un
progetto. In realtà questo scenario richiama un caso d’uso elencato precedentemente: New
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
66
experiment. Dallo schema dei casi d’uso si nota che la creazione di un nuovo esperimento
include il caso d’uso New project. Il sequence diagram rappresentato illustra lo scambio di
messaggi che avviene tra quattro entità importanti: l’utente (in qualità di attore),
l’interfaccia grafica del tool, il file xml generato ed utilizzato dal tool e il sistema operativo
che esegue alcuni comandi richiesti dal tool.
Utente :ToolGUI
crea nuovo progetto
inserisci nome progetto
progetto inserito con successo
:XML
aggiungi elemento project
crea nuovo esperimento
inserisci nome esperimento
aggiungi sottonodo experiment
esperimento inserito con successo
inserisci parametri config progetto
tool configurato con successo
seleziona path del file .od
:OS
richiesta elenco dei file .od del sistema
elenco dei file .od
visualizza elenco file
seleziona file desiderato
selezione del file desiderato
inizio attesa
simulazione della golden copy
emulazione
invio output emulazione
fine attesa
aggiungi sottonodo ad experiment
inserimento parametri
conferma valori inseriti
calcolo del valore "count"
esperimento configurato
richiesta valori inseriti
rilascio valori inseriti
visualizza valori inseriti
Figura 3.4: Sequence diagram: new experiment
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
67
Si osservi che i primi due messaggi inviati dall’utente ed il primo inviato dal tool servono
per la creazione di un progetto. Ad ogni avvio dell’applicazione non è possibile creare
nessun esperimento (o studio) senza un progetto esistente. Una funzione particolare svolta
dal sistema operativo riguarda l’emulazione della golden copy. Inoltre dopo che l’utente ha
inserito i parametri dell’esperimento, il tool ricava il valore di count in funzione della
locazione scelta.
3.5.2 Sequence diagram n°2: esecuzione di un progetto
Il sequence diagram che è oggetto di questo paragrafo richiama il caso d’uso Run project.
Si è scelto di analizzare questo caso sia perché è possibile comprendere, per sommi capi, il
funzionamento dell’AVR-INJECT tool da un punto di vista progettuale e sia perché ha
subito delle modifiche rispetto alla versione precedente del tool. In questo diagramma si
utilizzano le classi dell’applicazione e i messaggi scambiati corrispondono ad istanze di
nuovi oggetti e a chiamate di metodi con i rispettivi valori di ritorno (frecce in tratteggio).
Le entità chiamate in causa sono: l’utente, l’interfaccia grafica GUI associata alla classe
java ToolGUI, la classe Esperimento, la classe OD, la classe Riga, la classe ParseXMLFile,
la classe Iniezione, la classe Analisi Trace, la classe GenerateValChart, la classe
CreatePieChart, la classe CreateBarChart ed il sistema operativo. Osservando la figura 3.4,
che mostra il sequence diagram, si nota che il diagramma inizia con la creazione di un
esperimento questo perché è stato ipotizzato che il relativo progetto sia stato già creato in
precedenza.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
68
Figura 3.5: Sequence diagram: run project
Utente :ToolGUI :Esperimento :OD :Riga :ParseXMLFile :Iniezione
crea studio
studio creato
esegui progetto
simulazione avviata
<<create>>
init(pos)
<<create>>
<<create>>
<<create>>
albero dei nodi del file xml
<<create>>
checkinjection(ParseXMLFile.path,ParseXMLFile.ciclo[k],ParseXMLFile.tipo[k])
blocco stringhe checkinjection
injection(ParseXMLFile.maschera[k],ParseXMLFile.locazione[k],ParseXMLFile.tipo[k])
blocco stringhe injection
injection_core
blocco stringhe instruction target
modificaGC()
blocchi accodati
creaDir()
salva() :OS
script()
emulazione
file creati
:AnalisiTrace :GenerateValChart :CreatePieChart :CreateBarChart
analizza(pathGC,pathEsp,ciclo,loc)
tipo errore
aggiorna(ciclo,bit,pathEsp)
calPercTot(pathEsp)savePieChart(path,nome,dati)
calPercCiclo(pathEsp)
savaBarChart(path,nome,dati)
calPercBitFlip(pathEsp)saveBarChart(path,nome,dati)
fine esecuzionevisualizza grafici
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
69
Nel sequence diagram di figura 3.5 si è ipotizzato che non si siano verificati errori di tipo
crash o hang, nel caso in cui si fosse verificato almeno uno dei due allora avremmo
dovuto inserire nel diagramma la classe CreateBarChartLat. In questo caso la classe
Esperimento avrebbe invocato il metodo calPercLat() della classe GenerateValChart e
quest’ultima a sua volte avrebbe invocato il metodo saveBarLat() della classe
CreateBarChartLat per la creazione del grafico della latenza.
3.6 Problematiche affrontate
In questo paragrafo analizziamo in dettaglio le problematiche affrontate durante la fase di
progettazione e mostriamo le soluzioni adottate.
Il principale problema riscontrato è relativo alla fase di analisi dei file di trace, necessaria
alla classificazione degli errori, ed è dovuto all’elevata dimensione dei file di trace
generati dall’emulatore Avrora (nell’ordine delle centinaia di MB per una simulazione di
due secondi). Per la classificazione degli errori, c’è la necessità di confrontare, istruzione
per istruzione, il file di trace della golden copy con quello dell’esperimento di fault
injection eseguito (fase di analisi), quindi un’elevata dimensione di questi file
provocherebbe un tempo di esecuzione eccessivo per la fase di analisi. La soluzione
adottata è quella di tagliare i file di trace conservando tutte le informazioni a partire dal
punto di iniezione in poi; il taglio effettuato non crea problemi in quanto prima del punto
di iniezione il trace della golden copy coincide con quello dell’esperimento (ovviamente
sono escluse dal confronto le istruzioni introdotte per effettuare la fault injection). Per il
taglio dei file di trace, abbiamo deciso di utilizzare i file ad accesso casuale di java
(sfruttando la classe RandomAccessFile) per posizionarci in modo diretto sul punto di
iniezione; tuttavia il metodo seek() utilizzato, richiede di specificare di quanto spostare il
puntatore al file rispetto all’inizio del file, in termini di numero di byte. Per ricavare
l’offset (numero di byte) abbiamo creato un apposito script, che memorizza in un file tutte
le occorrenze della locazione di iniezione (ricavate dal file di trace) mostrando per ognuna
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
70
di essa il relativo offset; per chiarezza riportiamo di seguito lo script creato:
source /etc/bash.bashrc
cat esp_Trace.txt | grep -b 216C: > Outgrep.txt
cat TraceBlink.txt | grep -b 216C: > Outgrepgc.txt
exit
Nell’esempio mostrato la locazione in cui iniettare il fault è 216C. Tra tutti i valori
disponibili, il valore di offset da utilizzare viene scelto in base al ciclo di iniezione
specificato dall’utente, ad esempio se l’utente scegliesse il secondo ciclo per l’iniezione,
allora verrebbe scelto il valore di offset relativo alla seconda occorrenza della locazione in
cui si vuole iniettare il fault. Con questo meccanismo, le dimensioni dei file di trace si
riducono mediamente di un fattore 100 (ad esempio passando da qualche centinaia di MB
a qualche MB).
Un altro problema affrontato è stato quello di escludere, dal confronto eseguito nella fase
di analisi, le istruzioni introdotte per la fault injection; vi è la necessità di escludere queste
istruzioni, in quanto, se fossero considerate verrebbero sempre riscontrate delle differenze
(anche nel caso in cui non ci sono) tra il file di trace dell’esperimento di fault injection e
quello della golden copy. E’ importante ricordare che la modifica al file disassemblato per
la realizzazione della fault injection, comporta l’inserimento di blocchi di istruzioni in
coda al file. Quindi per inserire questi blocchi di istruzione e calcolare automaticamente le
locazioni di memoria occupate, il tool calcola qual è l’ultima locazione di memoria
occupata dalle istruzioni del file disassemblato. Questa informazione ci permette di
escludere dal confronto (effettuato nella fase di analisi) tutte le istruzioni che hanno un
indirizzo di memoria superiore all’ultimo; in questo modo non sono considerate le
istruzioni relative alle sezioni di: CheckInjection, Injection ed InstructionTarget.
Riportiamo di seguito la porzione di codice che ci permette di effettuare l’esclusione:
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
71
if (indesp.equals(indfault)||(indesp.compareTo(la stline)>=0))
{
rigaesp=fesp.readLine();
posesp=fesp.getFilePointer();
tokenesp=tokenizer(rigaesp," ");
indesp=(String)tokenesp.elementAt(2);
indesp=indesp.substring(0, indesp.length()-1);
while ((indesp.compareTo(lastline)>=0)&&(posesp<finesp-40 0))
{
rigaesp=fesp.readLine();
posesp=fesp.getFilePointer();
tokenesp=tokenizer(rigaesp," ");
indesp=(String)tokenesp.elementAt(2);
indesp=indesp.substring(0, indesp.length()-1);
}
}
Nella porzione di codice indfault indica la locazione in cui si vuole iniettare il fault, indesp
rappresenta la locazione corrente ricavata dal file di trace e finesp rappresenta la fine del
file di trace. E’ importante notare che per ricavare le locazioni di memoria su cui effettuare
il confronto viene utilizzata la procedura tokenizer.
Infine un ulteriore problema affrontato è quello dell’individuazione di cicli di istruzioni
durante la fase di analisi, è importante individuare questi cicli in quanto il loro
manifestarsi è uno dei sintomi della presenza di un hang error. Il problema in questo
caso è l’individuazione bel blocco di istruzioni che si ripete in quanto non si conosce
neanche la sua lunghezza; per questo problema è stato implementata un’apposita
procedura. Questa procedura utilizza i file ad accesso casuale di java (sfruttando la classe
RandomAccessFile) per lo spostamento all’interno del file; infatti quando è individuato un
ciclo vengono saltate tutte le sue istruzioni. Per individuare un ciclo, visto che non si
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
72
conosce la lunghezza, viene ispezionato il file di trace considerando 50 istruzioni per volta
che sono memorizzate all’interno di un array; il meccanismo è di confrontare un’istruzione
dell’array con le altre finché non viene riscontrata un’uguaglianza a quel punto si
confrontano le due istruzioni successive (rispetto a quelle riscontrate uguali) e così via
finché non si incontra una differenza (vuol dire che il ciclo è terminato). A questo punto si
ripete il procedimento partendo dall’istruzione successiva rispetto a quella che rappresenta
l’ultima istruzione del ciclo individuato. Riportiamo di seguito il codice della procedura:
poscorrente=posfirstdiff;
while ((poscorrente<finesp-400-2000)&&(numCicli<2 000))
{
fesp.seek(poscorrente);
for (int i=0; i<50; i++)
{
rigaesp=fesp.readLine();
posesp=fesp.getFilePointer();
tokenesp=tokenizer(rigaesp," ");
indesp=(String)tokenesp.elementAt(2);
indesp=indesp.substring(0, indesp.length()-1);
cEsp=(String)tokenesp.elementAt(1);
arrayInd[i]=indesp;
arrayPos[i]=posesp;
arrayCicli[i]=cEsp;
}
poscorrente=fesp.getFilePointer();
for (int i=0; i<50; i++)
{
int j=i+1;
while ((j<50))
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
73
{
if (arrayInd[i].equals(arrayInd[j]))
{
lunghezza=j-i;
l=i+1;
trovCiclo=true;
fesp.seek(arrayPos[j]);
while ((l<lunghezza+i+1)&&(trovCiclo))
{
rigaesp=fesp.readLine();
posesp=fesp.ge tFilePointer();
tokenesp=tokenizer(rigaesp," ");
indesp=(String)tokenesp.elementAt(2);
indesp= indesp.substring(0,indesp.length()-1);
if (!(arrayInd[l].equals(indesp)))
trovCiclo=false;
l++;
}
if (trovCiclo)
{
numCicli++;
if (numCicli==1)
espCiclo=arrayCicli[i];
j=j+lunghezza;
}
}
j++;
}
if (trovCiclo)
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
74
i=i+(2*lunghezza);
}
E’ interessante notare che la procedura termina o quando si raggiunge la fine del file di
trace oppure quando sono individuati 2000 cicli (che è un valore sufficientemente
rilevante per la presenza di un hang error). Inoltre è stato scelto, come limite alla
lunghezza del ciclo, un valore pari a 50 in quanto si è notato che la lunghezza media non
supera il valore 30. Infine vengono utilizzati tre array che memorizzano: le locazioni di
memoria che sono analizzate (arrayInd) , le posizioni del puntatore al file di trace relative
alle varie locazioni (arrayPos) ed il valore dei cicli macchina eseguiti relativamente alle
varie locazioni (arrayCicli, queste ultime informazioni sono necessarie per il calcolo della
latenza).
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
75
Capitolo 4
AVR-INJECT Tool: esecuzione di un progetto
In questo capitolo si vuole mostrare al lettore, attraverso l’ausilio di alcune schermate,
come configurare ed utilizzare l’AVR-INJECT Tool per l’esecuzione di un progetto. In
particolare focalizzeremo la nostra attenzione sull’esecuzione di un progetto contenente
uno studio step-by-step in quanto questa tipologia di studio è stata utilizzata per realizzare
la campagna di fault injection descritta nel capitolo successivo.
4.1 Creazione e configurazione di un progetto
All’avvio del tool, la prima schermata che compare all’utente è la seguente:
Figura 4.1: Avvio del tool
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
76
L’utente per poter iniziare una fault injection deve necessariamente creare un nuovo
progetto (figura 4.2). Supponiamo che l’utente decida di inserire uno studio step-by-step
nel progetto (figura 4.3). E’ bene ricordare che uno studio è un insieme di esperimenti e
che nel caso di studio step-by-step l’utente deve specificare gli intervalli di variazione del
bit-flip e dell’istante di iniezione. Una volta generato un progetto ed aver scelto di
effettuare uno studio, occorre configurare il progetto indicando al tool i parametri necessari
per la fault injection quali la piattaforma del microcontrollore, il tempo di simulazione,
l’archivio jar per eseguire l’emulatore Avrora e il percorso della cartella in cui si salvano
tutti i risultati relativi al progetto configurato. Nella figura 4.4 sono illustrati i campi da
settare i cui valori sono stati inseriti a scopo esemplificativo: si noti che ad ogni operazione
eseguita, il tool rilascia un messaggio di log nella finestra in basso alla schermata (Log
messages).
Figura 4.2: Creazione nuovo progetto
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
77
E’ importante precisare che prima di impostare qualsiasi esperimento o studio (step-by-
step o random) è fondamentale, per un corretto funzionamento del tool, la configurazione
Figura 4.3: Creazione nuovo studio step-by-step
Figura 4.4: Configurazione progetto
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
78
del progetto padre che li contiene. Infatti per impostare un esperimento o uno studio, il tool
utilizza i parametri scelti durante la configurazione del progetto.
4.2 Configurazione di uno studio step-by-step
Seguendo l’esempio del paragrafo precedente, supponiamo dunque che nel progetto
l’utente abbia deciso di eseguire uno studio di fault injection al variare del bit-flip e
dell’istante di iniezione. Occorre configurarlo, impostando il tipo di guasto da simulare
(tipo codice, memoria, nei registri Program Counter, Status Register e Stack Pointer),
l’intervallo di variazione del bit da flippare e l’intervallo di variazione dell’istante di
iniezione (dato che un’istruzione può essere eseguita più volte indica in quale di queste
iniettare il fault), il percorso del file disassemblato (con estensione .od) relativo
all’applicazione in cui si vuole effettuare la fault injection ed infine la locazione (o le
locazioni) in cui iniettare il fault.
La prima cosa da fare è selezionare il file .od di riferimento per la fault injection. Per il
particolare esempio abbiamo utilizzato il file BlinkAppCNO.od (figura 4.5).
Figura 4.5: Selezione file disassemblato
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
79
In seguito alla conferma del file scelto, il tool mette in attesa l’utente mascherando in
effetti un’operazione molto importante: il calcolo del valore count (numero di volte che
l’istruzione target scelta viene eseguita). In altre parole, quando l’utente viene messo in
attesa (attraverso la finestra di popup Waiting the task visualizzata in figura 4.6), il tool
provvede ad effettuare uno ‘studio del sistema target’ (fase di pre-injection), operazione
preliminare che serve a generare i file di trace e di profile della Golden Copy. Questo passo
è molto importante perché consente al tool di ricavare per ogni locazione inserita
dall’utente, il numero di esecuzioni della corrispondente istruzione (count number). A
questo punto è possibile capire l’importanza della configurazione iniziale del progetto:
infatti per ricavare il valore del count number, il tool esegue un comando che invoca
l’emulatore Avrora, per generare il file di profile, e che utilizza come parametri la
piattaforma ed il percorso del file jar di Avrora specificati durante la configurazione del
progetto.
Dopo che l’utente ha scelto il file disassemblato (nell’esempio BlinkAppCNO.od) deve
indicare il punto di iniezione. In uno studio è possibile inserire più di una locazione
Figura 4.6: Waiting the task
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
80
(injection point) purché siano separate dal carattere di virgola ‘,’. Per inserire le locazioni
di iniezione ci sono tre possibilità: l’utente può immettere direttamente le locazioni (in
forma esadecimale e separate dalla virgola) oppure può selezionarle da una lista (creata
appositamente dal tool al caricamento del file disassemblato – figura 4.7) oppure lascia il
campo vuoto delegando il tool nella scelta delle locazioni.
Per default il tipo di guasto da simulare è Code; nell’esempio noi lo impostiamo su
Memory così da simulare guasti nelle celle di memoria. Per default il valore iniziale, quello
finale e lo step per l’intervallo di variazione del bit-flip sono impostati ad 1; mentre il
valore iniziale, quello finale e lo step per l’intervallo di variazione che permette il calcolo
degli istanti di iniezione sono impostati rispettivamente a 0, 0.1 e 1. Per l’esempio, che è a
scopo illustrativo, abbiamo deciso di far variare il bit da flippare da 1 ad 8 con passo 1
(figura 4.8) mentre abbiamo deciso di effettuare l’iniezione alla prima esecuzione delle
istruzioni associate alle locazioni scelte (figura 4.9). In particolare per l’iniezione sono
state scelte due differenti locazioni 1102 e 145a (figura 4.10).
Figura 4.7: Selezione della locazione
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
81
Impostati tutti i valori necessari, si può confermare la configurazione dello studio (figura
4.11). In questo caso il tool mediante la finestra Log messages riporta un resoconto dei
parametri inseriti. Inoltre il tool provvede ad informare l’utente sul numero di esecuzioni
delle istruzioni coinvolte nella fault injection (count number).
Figura 4.8: Impostazione dei valori per il bit-flip
Figura 4.9: Impostazione dei valori per l’istante di iniezione
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
82
Figura 4.10: Scelta delle locazioni
Figura 4.11: Conferma dello studio step-by-step
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
83
4.3 Esecuzione di un progetto e visualizzazione dei risultati
In questo paragrafo descriviamo come avviene l’esecuzione di un progetto e come sono
visualizzati i risultati all’interno del tool, come progetto scegliamo quello descritto nei
paragrafi precedenti.
Le figure sovrastanti illustrano rispettivamente l’icona associata all’evento di esecuzione di
un progetto e il messaggio rilasciato dal tool quando la simulazione viene avviata. A
questo punto l’utente resterà in attesa dei risultati prodotti dall’AVR-INJECT Tool. In
particolare mostriamo di seguito il messaggio mostrato dal tool quando l’esecuzione è
terminata.
Quando la simulazione è conclusa c’è la possibilità di visualizzare i risultati all’interno del
tool attraverso l’albero di navigazione dei progetti. Riportiamo di seguito i risultati
ottenuti dall’esecuzione del progetto di esempio.
Figura 4.12: Esecuzione di un progetto
Figura 4.13: Fine esecuzione
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
84
In particolare si vede come la presenza di un grafico a torta che riporta le percentuali di
occorrenza delle tipologie di errori riscontrati, due istogrammi che riportano le percentuali
Figura 4.14: Risultati parte uno
Figura 4.15: Risultati parte due
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
85
di occorrenza degli errori al variare del bit-flip e del ciclo (istante) di iniezione. Inoltre nel
caso in cui sono rilevati errori di tipo crash o di tipo hang il tool genera anche il grafico
che riporta le percentuali di occorrenza di questi errori in funzione dei cicli di latenza
riscontrati (in particolare nel grafico di figura 4.15 si mostra la latenza riscontrata per gli
errori di tipo hang).
4.4 Files generati dal tool
L’utente, all’atto della configurazione di un progetto, indica il percorso della cartella che
contiene i file creati dal tool. L’organizzazione delle cartelle è la seguente: il tool crea
innanzitutto una cartella chiamata Project x (la x indica il nome scelto dall’utente per un
particolare progetto); l’applicazione poi crea all’interno di suddetta cartella, un numero di
cartelle pari al numero di studi ed esperimenti inclusi in un progetto. Inoltre i nomi di
queste cartelle riportano il tipo ed il nome dell’esperimento.
Nella figura 4.16 viene mostrato il contenuto della cartella che contiene i risultati dello
studio eseguito.
Figura 4.16: File contenuti nella cartella del progetto eseguito
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
86
Dalla figura 4.16 si nota la presenza dei grafici generati dal tool e mostrati in precedenza,
ed una cartella per ognuna delle locazioni specificate. Riportiamo di seguito un grafico che
contiene tutti i file generati dal tool per un particolare esperimento di fault injection (in
particolare quello relativo alla locazione 145a con bit flip 5 e ciclo di iniezione pari ad 1).
Descriviamo di seguito brevemente i vari file generati dal tool.
4.4.1 File Esp_*.od
Si tratta di un codice disassemblato in cui a differenza di quello della Golden Copy vi sono
ulteriori blocchi di codice per la gestione della fault injection. In particolare sono presenti i
blocchi di: CheckInjection, Injection ed InstructionTarget come previsto dalla tecnica di
fault injection utilizzata dal tool (tecnica di iniezione a livello assembly basata
sull’iniezione di codice).
Figura 4.17: File contenuti nella cartella di un particolare esperimento di fault injection
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
87
4.4.2 File esp_avrora.txt
E’ il primo file generato dall’emulatore Avrora. In esso vi è la simulazione che descrive gli
eventi, gli istanti temporali e i nodi associati ad uno degli eventi.
Nella particolare applicazione di prova (Blink) un evento rappresenta la transizione dello
stato di uno dei tre led del sensore (on -> off e viceversa).
4.4.3 File esp_Memory.txt
In certi contesti può risultare molto interessante osservare il comportamento della memoria
di un programma. Ad esempio sarebbe utile conoscere se un programma alloca locazioni di
memoria riservate cioè non utilizzabili oppure se si verifica un problema di overflow nello
stack di memoria. Per tale motivo, si utilizza uno dei monitor messi a disposizione
dall’emulatore Avrora: il memory monitor. Esso consente ai programmatori di esaminare il
comportamento della memoria di un programma e creare un report in cui si riportano le
locazioni di memoria con le rispettive percentuali di utilizzo in lettura e scrittura. Tale
report è anche utile per verificare eventuali accessi in memoria non consentiti.
4.4.4 Files esp_Profile.txt e esp_Calls.txt
I files esp_Profile.txt ed esp_Calls.txt sono generati dall’emulatore Avrora impostando il
parametro monitor rispettivamente a profile e calls.
Il primo monitor (profile) registra il numero di esecuzioni di ogni istruzione in un
programma. Il secondo monitor (calls) gestito dal simulatore riporta tutte le chiamate e le
interruzioni eseguite dal programma.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
88
4.4.5 File Trace.txt
Inizialmente all’interno della cartella è contenuto il file esp_Trace.txt ottenuto
dall’emulatore Avrora impostando il parametro monitor a trace; questo file riporta tutte le
istruzioni coinvolte nell’esecuzione dell’applicazione. Il file Trace.txt è ottenuto dal file
esp_Trace.txt scartando tutte le istruzioni che precedono il punto di iniezione; quando la
creazione del file è terminata il file esp_Trace.txt è cancellato allo scopo di limitare
l’occupazione di memoria necessaria a contenere le informazioni relative alla fault
injection realizzata.
4.4.6 File avr.sh
Il file avr.sh è uno script che raccoglie una serie di comandi interpretati dalla shell testuale
Bash. Attraverso la Bash l’utente è in grado di comunicare con il sistema operativo.
Attraverso questo script è invocato l’emulatore Avrora impostando opportunamente i
monitor in modo da generare i file descritti in precedenza. Il tool, nel corso
dell’esecuzione di un esperimento, crea ogni volta un nuovo script bash che viene salvato
insieme agli altri file di output.
4.4.7 File avrGrep.sh
Il file avrGrep.sh è uno script che raccoglie una serie di comandi interpretati dalla shell
testuale Bash. Questo script ci permette di conoscere la posizione di ogni occorrenza
dell’istruzione target (istruzione in cui si vuole iniettare il fault) all’interno del file
esp_Trace.txt espressa in termini di numero di byte. Inoltre lo script memorizza queste
informazioni all’interno del file Outgrep.txt.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
89
4.4.8 File Risultati.txt
Questo file contiene in forma testuale i risultati dell’analisi effettuata tra il file di trace
della Golden Copy e quello del particolare esperimento di fault injection. In particolare
oltre a riportare il tipo di errore riscontrato (hang, crash, errori latenti o errori da
approfondire) riporta le informazioni relative al numero di confronti effettuati, al numero
di differenze riscontrate ed il valore di latenza individuato.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
90
Capitolo 5
Utilizzo del tool: analisi comparativa tra TinyOS e Mantis
La campagna di fault injection realizzata ha lo scopo di mostrare le potenzialità dell’AVR-
INJECT tool confrontando il comportamento di due sistemi operativi, per reti di sensori
senza filo, molto diffusi: TinyOS e Mantis OS(MOS).
In particolare per il confronto sono state utilizzate due applicazioni target simili,
l'applicazione Blink per TinyOS e l'applicazione blink_led per MOS; inoltre per dimostrare
la generalità del tool sono stati effettuati alcuni esperimenti di fault injection anche
nell’applicazione sense_and_forward che è un’applicazione tipica per le reti di sensori
senza filo.
L’utilizzo dell'AVR-INJECT tool ci ha permesso di ottenere i risultati:
• più velocemente (mediamente un esperimento realizzato a mano richiede circa
dieci minuti mentre con il tool sono necessari circa cinque minuti).
• in modo più affidabile (sono esclusi possibili errori umani).
• in modo più preciso (in quanto il file di trace dell'esperimento è confrontato
istruzione per istruzione con quello della golden copy).
• in modo più intuitivo (i risultati ottenuti sono visualizzati graficamente).
Gli outcome, ovvero i risultati ottenuti, sono stati suddivisi in quattro categorie:
- Errori latenti : sono gli errori che non influenzano l'esecuzione del sistema
durante l'intervallo di tempo dell'esperimento.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
91
- Crash errors : sono conseguenze di un guasto che portano il sistema in uno
stato di malfunzionamento interrompendo la sua normale
esecuzione.
- Hang errors : sono errori che non provocano un arresto quasi istantaneo
del sistema ma lo conducono in uno stato di loop: un blocco
di istruzioni successive al punto di iniezione viene ripetuto
n volte provocando una situazione di stallo.
- Errori da approfondire : sono errori temporanei che portano il sistema a
divergere, in più punti e per piccoli intervalli di
tempo, dalla sua normale esecuzione per poi
successivamente riallinearsi ad essa.
L’obiettivo della campagna di fault injection realizzata è quello di effettuare un’analisi
comparativa tra Mantis OS e TinyOS rispetto al loro comportamento in presenza di guasti.
In particolare vogliamo valutare la robustezza ai guasti (in generale la robustezza di un
sistema è la misura in cui il sistema si comporta in modo ragionevole in situazioni
impreviste ossia non contemplate dalle specifiche; nel nostro caso le situazioni impreviste
riguardano la presenza di guasti) dei due sistemi operativi. Ad esempio, se un sistema ha
la percentuale maggiore di errori latenti possiamo dire in un certo senso che è più robusto
anche se tali errori potrebbero comunque attivarsi successivamente. In modo analogo, un
sistema che presenta una percentuale maggiore di errori di tipo crash è in un certo senso
più “safe” infatti visto che ne viene bloccata l’esecuzione si ha una probabilità minore che
si verifichino danni catastrofici. Invece un sistema che presenta la percentuale maggiore di
errori di tipo hang oppure di errori da approfondire comporta un problema di spreco di
risorse, infatti il carico elaborativo superiore comporta nel nodo sensore un consumo
energetico superiore.
Le metriche utilizzate per la valutazione sono le percentuali di occorrenza delle tipologie di
errore descritte in precedenza e la distribuzione di latenza ottenuta nei casi di errori di tipo
crash ed hang. La latenza è definita come il numero di cicli macchina che intercorrono dal
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
92
momento in cui si attiva l’iniezione (si verifica l’istante di iniezione) fino al momento in
cui l’iniezione agisce effettivamente sul sistema (provocando un crash error o un hang
error).
Attraverso l'AVR-INJECT Tool è possibile iniettare guasti nel codice, in memoria e nei
registri del processore (PC, SP, SR) quindi la campagna di fault injection realizzata è stata
programmata in modo tale da coprire tutte queste tipologie di iniezione. In particolare per
ogni tipologia di iniezione sono stati eseguiti alcuni studi step-by-step nei quali la
locazione in cui effettuare l’injection è scelta in modo casuale mentre sono fissati gli
intervalli di variazione del ciclo e del bit flip. Per il bit flip l’intervallo di variazione è
unico, parte dal valore 1 ed arriva al valore 8 con passo 1. Per il ciclo (istante di iniezione)
l’intervallo di variazione standard parte da 0 ed arriva ad 1 con passo 0.2 (è bene ricordare
che questi valori sono normalizzati quindi al valore 1 corrisponde l’ultima esecuzione della
particolare locazione considerata). E’ importante precisare che il numero di esperimenti di
fault injection realizzati nelle varie locazioni non è sempre lo stesso; questo perché il
numero dei valori generati dall’intervallo di variazione del ciclo varia in funzione del count
associato alla locazione scelta (il count indica quante volte la locazione viene richiamata).
Riportiamo di seguito una tabella che riassume il numero di esperimenti di fault injection
eseguiti suddivisi per tipologia di iniezione:
Codice Memoria PC SP SR
Mantis OS 432 304 432 280 304
TinyOS 312 328 280 296 304
Nei paragrafi successivi analizziamo in modo dettagliato i risultati ottenuti, sia per Mantis
che per TinyOS.
5.1 Fault injection in Mantis OS
Per analizzare in modo più dettagliato i risultati ottenuti, li presentiamo prima suddivisi
Tabella 5.1: Esperimenti di fault injection suddivisi per tipologia di iniezione
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
93
per tipologia di iniezione e poi successivamente in una visione di insieme.
5.1.1 Code Error Injection
Il grafico a torta sottostante mostra i risultati della campagna di fault injection ottenuti,
attraverso l’utilizzo dell’AVR-INJECT Tool, iniettando guasti nel codice
dell’applicazione blink_led. Sono stati realizzati 432 esperimenti di fault injection raccolti
in 12 studi step-by-step.
Su 432 esperimenti di fault injection effettuati nel codice dell’applicazione:
• il 33,3% degli esperimenti ha provato la robustezza dell’applicazione blink_led.
L’iniezione del guasto non ha influenzato il suo normale funzionamento.
• il 2,1% degli esperimenti ha riportato un caso di Hang Error .
• l’1,4% degli esperimenti ha riportato un caso di Crash Error.
• il 63,2% degli esperimenti ha riportato un caso di errore che merita ulteriori
approfondimenti.
Figura 5.1: Grafico a torta che riporta i risultati degli esperimenti di iniezione nel codice
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
94
Per brevità nella tabella seguente si riportano solo le locazioni ottenute dal tool, il numero
di esperimenti ad essi associati, le procedure e i tipi di errore riscontrati.
Locazione Procedura Hang
Error
Crash
Error
Errori
latenti
Errori da
approfondire
12e0 hardware_id_init 6 0 0 10
1f0 start 0 5 0 3
2232 mica2_battery_init 0 0 0 8
236 mos_led_init 0 0 0 8
284 mos_led_off 0 0 0 8
3116 __vector_22 0 0 8 0
3a2 plat_init 0 1 0 7
47cc mos_thread_wakeup_noints 0 0 32 64
4be0 mos_thread_sleep 0 0 88 8
4d70 mos_mem_alloc 0 0 8 64
4de6 mos_mem_free 3 0 0 5
51a2 mos_tlist_ordadd 0 0 8 88
Dalla tabella si nota che per alcune locazioni sono stati effettuati solo 8 esperimenti di
fault injection questo vuol dire che le relative istruzioni sono eseguite una sola volta e
quindi l’istante di iniezione (ciclo) è sempre lo stesso; di conseguenza gli esperimenti sono
eseguiti solo al variare del bit-flip da 1 ad 8 con passo 1. Invece per altre locazioni sono
stati effettuati un numero di esperimenti di fault injection multipli di 8, questo vuol dire
che gli esperimenti sono eseguiti variando sia il bit-flip che il ciclo d’iniezione.
Inoltre guardando la tabella possiamo affermare che in generale, fissata la locazione, la
variazione della tipologia di errore rispetto alla variazione del bit-flip e del ciclo di
iniezione è bassa. E’ interessante quindi analizzare più in dettaglio un caso in cui c’è una
Tabella 5.2: Parametri utilizzati per la campagna di fault injection nel codice e outcome
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
95
variabilità rispetto al bit-flip e all’istante di iniezione. Riportiamo di seguito una porzione
di codice della procedura hardware_id_init che contiene la locazione 12e0 :
12d8: 0e 94 fe 08 call 0x11fc ; 0x11fc <read_byte > 12dc: 89 93 st Y+, r24 12de: 82 e0 ldi r24, 0x02 ; 2 12e0: c9 36 cpi r28, 0x69 ; 105 12e2: d8 07 cpc r29, r24 12e4: c9 f7 brne .-14 ; 0x12d8 <h ardware_id_init+0x96>
In particolare in seguito all’iniezione effettuata viene modificato uno dei bit del registro
r28, quindi il contenuto di tale registro viene confrontato con un valore immediato.
L’istruzione successiva anche se non utilizzata direttamente il valore del registro r28, che
è stato modificato, viene influenzata indirettamente dal risultato dell’istruzione precedente
(l’esecuzione dell’istruzione target modifica alcuni flag del registro SR). La presenza di
errori di tipo Hang, per gli esperimenti di fault injection realizzati in questa locazione, è
dovuta all’istruzione di salto condizionato all’indietro (brne -14) nelle immediate
vicinanze dell’istruzione target (istruzione in cui è stato iniettato il fault); infatti
l’iniezione effettuata può in alcuni casi modificare la condizione di salto in modo da
generare un loop (essendo un salto condizionato relativo con spiazzamento negativo se la
condizione di salto è sempre verificata allora vengono eseguite ripetutamente le stesse
istruzioni).
Un altro studio di fault injection che è interessante approfondire è quello relativo alla
locazione 4be0 in cui si sono riscontrati ben 88 casi di errori latenti. Riportiamo di seguito
una porzione di codice della procedura mos_thread_sleep che contiene la locazione 4be0:
4bd8: 0e 94 b4 28 call 0x5168; 0x5168 <mos_tlist_ordadd>
4bdc: 80 91 71 03 lds r24, 0x0371 4be0: 6d 2d mov r22, r13 4be2: 99 27 eor r25, r25 4be4: 0e 94 c6 23 call 0x478c; 0x478c <mos_thread_wakeup_noints> 4be8: 1f 91 pop r17 4bea: 0f 91 pop r16 4bec: ff 90 pop r15 4bee: ef 90 pop r14 4bf0: df 90 pop r13 4bf2: 08 95 ret
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
96
Dal codice si capisce che i vari esperimenti di fault injection realizzati modificano uno dei
bit del registro r22. In questo caso l’elevato numero di errori latenti riscontrati è dovuto al
fatto che nelle immediate vicinanze dell’istruzione in cui si è iniettato il fault non viene
utilizzato il valore del registro r22.
Nel grafico successivo (istogramma) si riportano le percentuali degli errori di Crash ed
Hang che si sono verificati nel corso dei 432 esperimenti in funzione dei cicli di latenza
riscontrati.
Dall’istogramma si possono trarre delle conclusioni interessanti. In primo luogo la
maggior parte degli errori (60%) ha una latenza che non supera i 90 cicli (essendo
l’ATmel128L un processore RISC corrispondono a circa 90 istruzioni). Inoltre dalla
tabella 5.2 notiamo che su 432 esperimenti si sono verificati 9 casi di errori di tipo Hang
(tre dei quali nella locazione 4de6 con latenza di 90 cicli ed i restanti sei nella locazione
12e0 con latenza superiore a 160 cicli in particolare il valore massimo di latenza
riscontrato è di 30850 cicli macchina) e 6 casi di errori di tipo Crash tutti con una latenza
che non supera i 70 cicli. In base ai risultati ottenuti, possiamo affermare che
relativamente alla fault injection realizzata nel codice la latenza degli errori di tipo Hang è
maggiore di quella degli errori di tipo Crash.
Figura 5.2: Latenza relativa all’iniezione nel codice
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
97
5.1.2 Memory Error Injection
Il grafico a torta sottostante mostra i risultati della campagna di fault injection ottenuti,
attraverso l’utilizzo dell’AVR-INJECT Tool, iniettando guasti in memoria. Sono stati
realizzati 304 esperimenti di fault injection raccolti in 18 studi step-by-step. Come si nota
dal grafico per questa tipologia di iniezione si ha una prevalenza di errori latenti con una
percentuale del 55,5%.
Bisogna notare che in questo caso, rispetto all’iniezione nel codice, sono aumentate le
percentuali di Crash Error e di errori latenti a discapito della percentuale degli errori da
approfondire, mentre sono completamente assenti gli errori di tipo Hang (presumibilmente
questo è dovuto al fatto che durante gli esperimenti di fault injection eseguiti non sono
state modificate le condizioni di terminazione dei cicli). In base a questo risultato
possiamo affermare che Mantis è più robusto ai bit flip indotti nella memoria rispetto a
quelli indotti nel codice.
Figura 5.3: Grafico a torta che riporta i risultati degli esperimenti di iniezione in memoria
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
98
Per brevità nella tabella seguente riportiamo solo le locazioni ottenute dal tool, il numero
di esperimenti ad essi associati, le procedure ed i tipi di errore riscontrati.
Locazione Procedura Hang
Error
Crash
Error
Errori
latenti
Errori da
approfondire
1dde select 0 8 0 0
2e62 __vector_21 0 0 16 0
2e78 __vector_21 0 0 8 0
30a6 __vector_22 0 0 24 0
432e dispatcher 0 0 24 8
1cfa atmel_flash_init 0 0 0 8
4346 dispatcher 0 0 32 8
441a dispatcher 0 0 32 8
444e mos_thread_exit 0 0 8 0
477c mos_thread_new 0 0 0 8
4880 mos_thread_resume_noints 0 0 8 0
4f0e mos_mutex_unlock 0 8 0 0
5084 mos_sem_post_dispatch 0 0 8 0
563a __vector_12 0 0 0 8
571c __vector_12 0 0 8 40
5742 __vector_12 0 0 0 8
9d6 com_init 0 0 0 8
b14 com_swap_bufs 0 0 0 16
Dalla tabella si nota che si verificano solo 16 casi di errori di tipo Crash distribuiti
uniformemente in due studi di fault injection, analizziamo in maggior dettaglio quello
relativo alla locazione 4f0e. Riportiamo di seguito una porzione di codice della procedura
Tabella 5.3: Parametri utilizzati per la campagna di fault injection in memoria e outcome
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
99
mos_mutex_unlock che contiene al suo interno la locazione 4f0e:
4f04: cf 93 push r28
4f06: df 93 push r29 4f08: ec 01 movw r28, r24 4f0a: 00 91 f6 04 lds r16, 0x04F6 4f0e: 10 91 f7 04 lds r17, 0x04F7 4f12: 0e 94 4f 20 call 0x409e ; 0x409e <mos_disable_ints> 4f16: f8 2e mov r15, r24 4f18: 88 81 ld r24, Y
4f1a: 99 81 ldd r25, Y+1 ; 0x01
In questo caso il fault iniettato provoca la modifica di uno dei bit del registro r17 inoltre il
contenuto modificato del registro viene scritto nella locazione 0x04F7 (nella sezione di
Injection viene inserita l’istruzione sts 0x04F7, r17) . In questo caso l’errore di tipo Crash
può essere dovuto alla modifica della locazione 04F7 la quale probabilmente contiene al
suo interno una parte di un indirizzo (infatti a supporto della nostra tesi si nota, dalla
porzione di codice riportata, che nel registro r16 viene caricato il contenuto della locazione
precedente di indirizzo 0x04F6). L’errore di Crash si manifesta quando la procedura in
esame termina ossia quando viene restituito il controllo al chiamante attraverso
l’istruzione ret, molto probabilmente perché l’indirizzo di ritorno non è più corretto.
Un altro studio di fault injection interessante è quello relativo alla locazione 2e62 in
quanto sono rilevati solo errori latenti. Riportiamo di seguito una porzione di codice della
procedura __vector_21 che contiene la locazione 2e62:
2e5c: 39 2b or r19, r25
2e5e: 30 93 e1 02 sts 0x02E1, r19 2e62: 20 93 e0 02 sts 0x02E0, r18 2e66: 89 ed ldi r24, 0xD9 ; 217 2e68: 92 e0 ldi r25, 0x02 ; 2 2e6a: 0e 94 2d 28 call 0x505a; 0x505a <mos_ sem_post_dispatch> 2e6e: ff 91 pop r31 2e70: ef 91 pop r30 2e72: bf 91 pop r27
In questo caso l’iniezione effettuata modificando uno dei bit del registro r18 modifica
anche il contenuto della locazione di memoria di indirizzo 02E0. Tuttavia gli errori rilevati
sono tutti errori latenti in quanto nelle immediate vicinanze dell’istruzione target
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
100
(istruzione in cui è stato iniettato il fault) non viene utilizzato né il valore contenuto nella
locazione di memoria di indirizzo 02E0 e nemmeno il valore contenuto nel registro r18.
Nel grafico successivo si riportano le percentuali degli errori, di tipo Crash ed Hang, che si
sono verificati nel corso dei 304 esperimenti in funzione dei cicli di latenza riscontrati.
Dall’istogramma si nota l’assenza degli errori di tipo Hang e che tutti gli errori di tipo
Crash hanno una latenza che non supera i 100 cicli. In particolare in base alla tabella 5.3
notiamo che su 304 esperimenti di fault injection si sono verificati solamente 16 casi di
errori di tipo Crash distribuiti in modo uniforme su due locazioni (nella locazione 1dde si
sono verificati 8 errori di tipo Crash con latenza nulla mentre nella locazione 4f0e si sono
verificati 8 errori di tipo Crash con latenza pari a 100 cicli macchina).
Figura 5.4: Latenza relativa all’iniezione in memoria
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
101
5.1.3 PC Error Injection
Il grafico a torta sottostante mostra i risultati della campagna di fault injection ottenuti,
attraverso l’utilizzo dell’AVR-INJECT Tool, iniettando guasti nel registro PC. Sono stati
realizzati 432 esperimenti di fault injection raccolti in 12 studi step-by-step. Dal grafico si
nota che la quasi totalità (il 94,5%) degli errori rilevati è rappresentata da errori di tipo
Crash.
E’ importante notare che in questa tipologia di iniezione sono completamente assenti
errori di tipo Hang; questo comportamento è dovuto all’iniezione effettuata infatti quando
viene modificato il contenuto del registro PC ci sono solamente due possibilità: l’indirizzo
ottenuto non è valido e viene quindi rilevato un Crash error oppure l’indirizzo ottenuto è
valido e si effettua il salto ad un’altra porzione di codice, tuttavia in quest’ultimo caso non
si generano loop in quanto non viene modificata la condizione di terminazione di un
eventuale ciclo.
Per brevità nella tabella seguente riportiamo solo le locazioni ottenute dal tool, il numero
di esperimenti ad essi associati, le procedure ed i tipi di errore riscontrati.
Figura 5.5: Grafico a torta che riporta i risultati degli esperimenti di iniezione nel PC
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
102
Locazione Procedura Hang
Error
Crash
Error
Errori
latenti
Errori da
approfondire
12e0 hardware_id_init 0 16 0 0
1f0 start 0 8 0 0
2232 mica2_battery_init 0 8 0 0
236 mos_led_init 0 8 0 0
284 mos_led_off 0 8 0 0
3116 __vector_22 0 8 0 0
3a2 plat_init 0 8 0 0
47cc mos_thread_wakeup_noints 0 96 0 0
4be0 mos_thread_sleep 0 96 0 0
4d70 mos_mem_alloc 0 48 8 16
4de6 mos_mem_free 0 8 0 0
51a2 mos_tlist_ordadd 0 96 0 0
Nel grafico successivo si riportano le percentuali degli errori, di tipo Crash ed Hang, che si
sono verificati nel corso dei 432 esperimenti in funzione dei cicli di latenza riscontrati.
Tabella 5.4: Parametri utilizzati per la campagna di fault injection nel PC e outcome
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
103
Dall’istogramma si nota come non siano presenti errori di tipo Hang e come tutti gli errori
di tipo Crash abbiano una latenza che non supera i 60 cicli (in particolare il valore di
latenza riscontrato è nullo in quanto il microcontrollore si accorge subito che l’indirizzo
non è valido e blocca l’esecuzione dell’applicazione). Inoltre dalla tabella 5.4 si nota come
in tutti gli studi di fault injection sono stati rilevati errori di tipo Crash.
5.1.4 SP Error Injection
Il grafico a torta sottostante mostra i risultati della campagna di fault injection ottenuti,
attraverso l’utilizzo dell’AVR-INJECT Tool, iniettando guasti nel registro SP. Sono stati
realizzati 280 esperimenti di fault injection raccolti in 20 studi step-by-step. Dal grafico si
nota come la percentuale maggiore di occorrenza sia quella degli errori di tipo Crash
(62,1%). Questo risultato deriva dalla struttura di Mantis, infatti quest’ultimo essendo un
sistema operativo multithread associa uno stack ad ogni thread e realizza meccanismi per
Figura 5.6: Latenza relativa all’iniezione nel registro PC
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
104
il controllo dei limiti di tale area, quindi quando in seguito all’iniezione del fault si
modifica il contenuto del registro SP si può tentare l’accesso ad un’area non consentita e
quindi viene bloccata l’esecuzione dell’applicazione.
Nella tabella seguente si riportano solo le locazioni ottenute dal tool, il numero di
esperimenti ad essi associati, le procedure e i tipi di errore riscontrati.
Locazione Procedura Hang
Error
Crash
Error
Errori
latenti
Errori da
approfondire
11fe read_byte 0 7 0 1
1246 hardware_id_init 2 5 1 0
2ee4 adc_read_channel16 0 4 1 3
30a8 __vector_22 0 8 0 0
4338 dispatcher 0 40 0 0
444a mos_thread_exit 0 0 8 0
Figura 5.7: Grafico a torta che riporta i risultati degli esperimenti di iniezione nel registro SP
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
105
46e6 mos_thread_new 0 8 0 32
4786 mos_thread_new 0 16 0 0
4b90 check_sleep_time 2 6 0 0
4be8 mos_thread_sleep 1 4 0 43
4cba mos_mem_alloc 0 8 0 0
4f00 mos_mutex_unlock 0 8 0 0
4f4c mos_mutex_lock 0 7 0 1
4f9e mos_mutex_lock 0 8 0 0
502c mos_sem_post 5 3 0 0
505a mos_sem_post_dispatch 1 15 0 0
5642 __vector_12 0 8 0 0
5652 __vector_12 0 8 0 0
5732 __vector_12 0 8 0 0
9d8 com_init 5 3 0 0
Dalla tabella si nota, rispetto ai casi precedenti, una variabilità maggiore rispetto alla
variazione del bit-flip e del ciclo di iniezione. Visto che la maggior parte degli errori è di
tipo Crash (ed abbiamo già spiegato intuitivamente il perché) è interessante approfondire
uno studio in cui sono stati rilevati errori di altra natura, ad esempio quelli di tipo Hang.
Riportiamo di seguito una porzione di codice della procedura mos_sem_post che contiene
la locazione 502c:
502a: 0f 93 push r16
502c: 1f 93 push r17 502e: 8c 01 movw r16, r24 5030: 0e 94 4f 20 call 0x409e ; 0x409e <mos _disable_ints> 5034: f8 2e mov r15, r24 5036: f8 01 movw r30, r16
Lo studio di fault injection relativo alla locazione 502c rileva la presenza di 5 casi di errori
di tipo Hang, questo probabilmente è dovuto alla presenza dell’istruzione di call (chiamata
Tabella 5.5: Parametri utilizzati per la campagna di fault injection nel registro SP e outcome
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
106
a procedura) nelle vicinanze dell’istruzione target. Infatti in seguito all’iniezione del fault
viene modificato il contenuto dello SP e di conseguenza in seguito alla chiamata a
procedura l’indirizzo di ritorno (che è salvato nello stack) potrebbe essere salvato in
locazioni non libere sovrascrivendo valori esistenti. In questo caso si può innescare un
ciclo nel momento in cui la procedura in esame restituisce il controllo al chiamante, infatti
visto che sono state sovrascritte alcune locazioni dello stack l’indirizzo di ritorno potrebbe
non essere più quello corretto. Per sostenere questa tesi riportiamo di seguito una porzione
di codice relativa alla procedura dispatcher che contiene la locazione 4338:
4336: af 92 push r10
4338: 9f 92 push r9 433a: 8f 92 push r8 433c: 7f 92 push r7 433e: 6f 92 push r6 4340: 5f 92 push r5 4342: 4f 92 push r4 4344: 3f 92 push r3 4346: 2f 92 push r2 4348: 8d b7 in r24, 0x3d ; 61 434a: 9e b7 in r25, 0x3e ; 62 434c: e0 91 f6 04 lds r30, 0x04F6 4350: f0 91 f7 04 lds r31, 0x04F7 4354: 91 83 std Z+1, r25 ; 0x01 4356: 80 83 st Z, r24 4358: 84 85 ldd r24, Z+12 ; 0x0c 435a: 81 30 cpi r24, 0x01 ; 1
E’ importante notare come in questo caso non siano presenti istruzioni di call vicino
all’istruzione target. In particolare, lo studio di fault injection sulla locazione in esame
riporta tutti errori di tipo Crash in quanto in seguito alla modifica del registro SP, vengono
sovrascritte locazioni dello stack e quindi quando la procedura termina restituendo il
controllo al chiamante (attraverso l’esecuzione dell’istruzione ret) l’indirizzo di ritorno
non è valido e l’esecuzione dell’applicazione viene interrotta.
Nel grafico successivo si riportano le percentuali degli errori, di tipo Crash ed Hang, che si
sono verificati nel corso dei 280 esperimenti in funzione dei cicli di latenza riscontrati.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
107
Dall’istogramma si nota che per questa tipologia di iniezione la latenza ha una variabilità
maggiore. In particolare la maggior parte degli errori (il 55,2%) ha una latenza che non
supera i 120 cicli. Dalla tabella 5.5 si nota che su 280 esperimenti di fault injection si
sono verificati 16 casi di errori di tipo Hang (distribuiti su più locazioni e con valore di
latenza che varia da 100 cicli fino ad arrivare in un caso isolato anche a 1475058 cicli) e
ben 174 casi di errori di tipo Crash (distribuiti su quasi tutte le locazioni e con valore di
latenza che varia a partire da un valore nullo fino ad arrivare ad un valore di 7271 cicli
macchina).
5.1.5 SR Error Injection
Il grafico a torta sottostante mostra i risultati della campagna di fault injection ottenuti,
attraverso l’utilizzo dell’AVR-INJECT Tool, iniettando guasti nel registro SR. Sono stati
Figura 5.8: Latenza relativa all’iniezione nel registro SP
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
108
totalizzati 304 esperimenti di fault injection raccolti in 14 studi step-by-step. Dal grafico si
nota che la percentuale di occorrenza maggiore (55,3%) è quella relativa agli errori latenti;
questo comportamento è strettamente legato al tipo di iniezione effettuata, infatti il fault
iniettato modifica uno dei bit del registro SR che con buona probabilità non è quello
utilizzato dall’istruzione target, inoltre dato che l’esecuzione di quasi tutte le istruzioni del
microcontrollore modifica lo stato del registro SR è possibile che già dopo poche
istruzioni (dal punto di iniezione) venga modificato il contenuto del registro SR evitando il
manifestarsi del fault.
Nella tabella seguente si riportano solo le locazioni ottenute dal tool, il numero di
esperimenti ad essi associati, le procedure e i tipi di errore riscontrati.
Locazione Procedura Hang
Error
Crash
Error
Errori
latenti
Errori da
approfondire
12e2 hardware_id_init 48 0 0 0
Figura 5.9: Grafico a torta che riporta i risultati degli esperimenti di iniezione nel registro SR
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
109
3118 __vector_22 0 0 0 16
312a __vector_22 0 0 16 0
318c dev_ioctl_DEV_AVR_EEPROM 0 0 8 0
3272 dev_read_DEV_AVR_EEPROM 0 0 0 8
40a0 mos_disable_ints 0 0 0 8
4130 mos_thread_resume_noints_nodispatch 0 0 8 0
418a idle_mode 0 0 8 0
41d6 idle_loop 0 0 0 8
430a dispatcher 0 0 72 8
4488 mos_thread_exit 0 0 8 0
46a8 mos_thread_new 0 0 8 24
47d2 mos_thread_wakeup_noints 0 0 40 8
4cda mos_mem_alloc 0 8 0 0
Dalla tabella si nota che su 304 esperimenti di fault injection si sono verificati solo 8 casi
di errori di tipo Crash (nella locazione 4cda) e 48 casi di errori di tipo Hang (nella
locazione 12e2). Per una maggiore comprensione analizziamo in dettaglio i casi di errori
di tipo Hang; riportiamo di seguito una porzione di codice della procedura
hardware_id_init che contiene la locazione 12e2:
12de: 82 e0 ldi r24, 0x02 ; 2
12e0: c9 36 cpi r28, 0x69 ; 105 12e2: d8 07 cpc r29, r24 12e4: c9 f7 brne .-14 ; 0x12d8 <h ardware_id_init+0x96> 12e6: 0e 94 fe 08 call 0x11fc ; 0x11fc <read _byte> 12ea: d4 98 cbi 0x1a, 4 ; 26 12ec: dc 98 cbi 0x1b, 4 ; 27
E’ interessante notare che l’iniezione del fault modifica uno dei bit del registro SR e che
tale modifica fa in modo che la condizione del salto relativo sia sempre verificata. Quindi
trattandosi di un salto relativo con valore dello spiazzamento negativo si genera un loop.
Tabella 5.6: Parametri utilizzati per la campagna di fault injection nel registro SR e outcome
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
110
Nel grafico successivo si riportano le percentuali degli errori, di tipo Crash ed Hang, che si
sono verificati nel corso dei 304 esperimenti in funzione dei cicli di latenza riscontrati.
Dall’istogramma si nota che gli errori di tipo Crash hanno una latenza che non supera i 60
cicli (con il valore minimo riscontrato che è nullo) mentre quelli di tipo Hang hanno una
latenza superiore ai 160 cicli (il massimo valore di latenza riscontrato è di 22540 cicli
macchina).
5.1.6 Mantis Total Error Injection
Il grafico a torta sottostante raggruppa i risultati delle campagne di fault injection, ottenuti
attraverso l’utilizzo dell’AVR-INJECT Tool, effettuando le differenti tipologie di
iniezione. Sono stati realizzati un totale di 1752 esperimenti raccolti in 76 studi step-by-
step. Dal grafico si nota che la percentuale di occorrenza maggiore (anche se di poco con il
36,8%) è quella relativa agli errori di tipo Crash. E’ importante notare che è elevata anche
Figura 5.10: Latenza relativa all’iniezione nel registro SR
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
111
la percentuale di occorrenza degli errori da approfondire (31,1%) e quella degli errori
latenti (25,7%) mentre invece è bassa quella degli errori di tipo Hang (solamente il 6,4%).
Inoltre in base alle tabelle riportate nei paragrafi precedenti si ricava che su 1752
esperimenti di fault injection si sono manifestati solo 113 casi di errori di tipo Hang
concentrati in dieci locazioni differenti.
Le percentuali degli errori, di tipo Crash ed Hang, che si sono verificati nel corso dei 1752
esperimenti in funzione dei cicli di latenza riscontrati, sono mostrate nel grafico
sottostante.
Figura 5.11: Grafico a torta che riporta i risultati globali degli esperimenti di iniezione.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
112
Dall’istogramma si nota che la percentuale degli errori di tipo Crash è molto più grande di
quella degli errori di tipo Hang. Inoltre mentre per gli errori di tipo Hang la latenza varia
in un range abbastanza ampio (dal minimo valore di latenza riscontrato che è di 70 cicli
macchina al massimo valore che è di 1475058 cicli macchina riscontrato in un caso
isolato) , nel caso di errori di tipo Crash il 69% ha una latenza che non supera i 60 cicli
(con un valore minimo di latenza che è nullo mentre il valore massimo riscontrato è di
7271 cicli macchina). In particolare il fatto di avere una latenza elevata risulta essere un
problema in quanto un’eventuale detector non potrebbe intervenire tempestivamente; un
detector ideale interviene (ossia rileva l’errore) subito dopo l’iniezione del fault (latenza
nulla).
Figura 5.12: Latenza totale in Mantis OS
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
113
5.2 Fault injection in TinyOS
Per analizzare in modo più dettagliato i risultati ottenuti in TinyOS, li presentiamo prima
suddivisi per tipologia di iniezione e poi successivamente in una visione di insieme.
5.2.1 Code Error Injection
Il grafico a torta sottostante mostra i risultati della campagna di fault injection ottenuti,
attraverso l’utilizzo dell’AVR-INJECT Tool, iniettando guasti nel codice
dell’applicazione blink. Sono stati realizzati 312 esperimenti raccolti in 13 studi step-by-
step.
Su 312 esperimenti di fault injection effettuati nel codice dell’applicazione:
• il 25,6% degli esperimenti ha provato la robustezza dell’applicazione blink.
L’iniezione del guasto non ha influenzato il suo normale funzionamento.
• il 31,1% degli esperimenti ha riportato un caso di Hang Error .
• il 24,7% degli esperimenti ha riportato un caso di Crash Error.
Figura 5.13: Grafico a torta che riporta i risultati degli esperimenti di iniezione nel codice
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
114
• il 18,6% degli esperimenti ha riportato un caso di errore che merita ulteriori
approfondimenti.
E’ importante notare che rispetto al grafico di figura 5.1 (iniezione nel codice di Mantis),
sono aumentate le percentuali di occorrenza degli errori di tipo Crash ed Hang mentre è
sensibilmente diminuita la percentuale degli errori da approfondire. L’aumento della
percentuale di occorrenza degli errori di tipo Crash può essere considerato in modo
positivo, in quanto, relativamente all’iniezione nel codice, possiamo dire che in un certo
senso TinyOS è più “safe” (negli errori di tipo Crash viene interrotta l’esecuzione
dell’applicazione evitando con maggiore probabilità il verificarsi di danni gravi). Invece
rispetto all’aumento della percentuale di occorrenza degli errori di tipo Hang e alla
diminuzione di quella degli errori da approfondire non possiamo effettuare osservazioni
interessanti in quanto entrambe le tipologie presentano soltanto aspetti negativi.
Nella tabella seguente si riportano le locazioni generate dal tool con le relative procedure,
il numero di esperimenti di fault injection eseguiti per ogni locazione ed i tipi di errore
riscontrati.
Locazione Procedura Hang
Error
Crash
Error
Errori
latenti
Errori da
approfondire
1006 HplCC1000P$HplCC1000$write 4 2 0 2
12e __nesc_atomic_end 0 0 0 8
143a VirtualizeTimerC$0$TimerFrom$startOneShotAt 0 0 0 32
14e6 AlarmToTimerC$0$start 0 0 32 0
1536 AlarmToTimerC$0$start 5 2 0 1
16a6 Atm128AlarmAsyncP$0$TimerCtrl$getInterruptFlag 48 0 0 0
1834 VirtualizeTimerC$0$fireTimers 0 32 0 0
1876 VirtualizeTimerC$0$Timer$fired 0 24 0 0
1ad2 SchedulerBasicP$TaskBasic$postTask 0 16 0 0
1b0c SchedulerBasicP$pushTask 40 0 0 0
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
115
21c8 HplAtm128Timer0AsyncP$stabiliseTimer0 0 0 48 0
72a HplAtm128GeneralIOPinP$6$IO$makeInput 0 0 0 8
fe __nesc_atomic_start 0 1 0 7
Analizziamo di seguito due casi notevoli scelti dalla tabella che ci permettono di
comprendere meglio come è stato possibile, in seguito all’iniezione effettuata, ottenere le
particolari tipologie di errori. Come casi notevoli abbiamo scelto la locazione 1b0c in cui
sono rilevati 40 errori di tipo Hang e la locazione 21c8 in cui sono rilevati 48 errori
latenti. Riportiamo di seguito una porzione di codice della procedura
SchedulerBasicP$pushTask che contenga al suo interno la locazione 1b0c:
1b08: 0f b6 in r0, 0x3f ; 63
1b0a: f8 94 cli 1b0c: de bf out 0x3e, r29 ; 62 1b0e: 0f be out 0x3f, r0 ; 63 1b10: cd bf out 0x3d, r28 ; 61 1b12: 89 83 std Y+1, r24 ; 0x01 1b14: 89 81 ldd r24, Y+1 ; 0x01 1b16: 0e 94 b7 0d call 0x1b6e 1b1a: 88 23 and r24, r24
In questo caso l’iniezione del fault provoca la modifica di uno dei bit del registro r29,
tuttavia visto che il valore contenuto nel registro r29 viene utilizzato per modificare la
parte alta del registro SP (SPH) di conseguenza in seguito all’iniezione viene modificato
anche lo stack pointer. Questa modifica comporta la sovrascrittura di alcune locazioni
dello stack con relativa perdita di valori, in questo modo il loop può essere innescato nel
momento in cui la procedura in esame restituisce il controllo al chiamante in quanto
l’indirizzo di ritorno non coincide con quello salvato in precedenza nello stack.
Riportiamo di seguito il codice della procedura HplAtm128Timer0AsyncP$stabiliseTimer0
che contiene al suo interno la locazione 21c8:
21c2: cf 93 push r28
21c4: df 93 push r29 21c6: cd b7 in r28, 0x3d ; 61 21c8: de b7 in r29, 0x3e ; 62 21ca: e3 e5 ldi r30, 0x53 ; 83 21cc: f0 e0 ldi r31, 0x00 ; 0
Tabella 5.7: Parametri utilizzati per la campagna di fault injection nel codice e outcome
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
116
21ce: a3 e5 ldi r26, 0x53 ; 83 21d0: b0 e0 ldi r27, 0x00 ; 0 21d2: 8c 91 ld r24, X 21d4: 80 83 st Z, r24 21d6: e0 e5 ldi r30, 0x50 ; 80 21d8: f0 e0 ldi r31, 0x00 ; 0 21da: 80 81 ld r24, Z 21dc: 99 27 eor r25, r25 21de: 81 70 andi r24, 0x01 ; 1 21e0: 90 70 andi r25, 0x00 ; 0 21e2: 88 23 and r24, r24 21e4: c1 f7 brne .-16 ; 0x21d6 21e6: df 91 pop r29 21e8: cf 91 pop r28 21ea: 08 95 ret
L’istruzione target carica nel registro r29 il contenuto della parte alta del registro SP,
l’iniezione del fault comporta la modifica di uno dei bit del registro r29. In questo caso
abbiamo riportato l’intera procedura per far notare come in seguito all’iniezione del fault il
valore contenuto dal registro r29 non sia più utilizzato ed è per questo che sono stati
rilevati tutti errori latenti.
Nel grafico successivo sono riportate le percentuali degli errori di Crash ed Hang che si
sono verificati nel corso dei 312 esperimenti in funzione dei cicli di latenza riscontrati.
Figura 5.14: Latenza relativa all’iniezione nel codice
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
117
Dall’istogramma si nota come l’89% degli errori abbiano una latenza che non supera gli
80 cicli. Inoltre dalla tabella 5.7 si nota che su 312 esperimenti di fault injection si sono
verificati 97 casi di errori di tipo Hang (distribuiti in quattro locazioni differenti con
latenza che varia da 70 a 645 cicli macchina ) e 77 casi di errori di tipo Crash (distribuiti in
sei locazioni differenti con valori di latenza che vanno da 0 e non superano i 60 cicli
macchina). Infine possiamo notare che rispetto all’istogramma di figura 5.2 (latenza nel
codice di Mantis OS), i cicli di latenza si sono ridotti sia per gli errori di tipo Crash
(passando da 70 a 60 cicli macchina) sia per quelli di tipo Hang (per la maggior parte di
essi la latenza è passata da un valore superiore a 160 ad un valore che non supera i 70 cicli
macchina). Questo comportamento è preferibile in quanto permetterebbe ad un eventuale
detector di intervenire più tempestivamente.
5.2.2 Memory Error Injection
Nel grafico seguente sono riportati i risultati della campagna di fault injection ottenuti,
attraverso l’utilizzo dell’AVR-INJECT Tool, iniettando guasti in memoria. In particolare,
sono stati realizzati 328 esperimenti di fault injection raccolti in 14 studi step-by-step.
Dal grafico si nota che la percentuale di occorrenza maggiore è quella relativa agli errori
latenti con il 44,2%. Rispetto ai risultati ottenuti in Mantis OS per questa tipologia di
iniezione (basta osservare il grafico a torta dei risultati di figura 5.3) notiamo la presenza
degli errori di tipo Hang e la diminuzione delle percentuali di occorrenza di quelli latenti e
da approfondire. Questo ci permette di affermare che, relativamente all’iniezione dei fault
in memoria, Mantis OS è più robusto rispetto a TinyOS.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
118
Di seguito riportiamo una tabella che contiene le locazioni generate (in modo casuale) dal
tool con le relative procedure, il numero di esperimenti di fault injection effettuati con la
relativa classificazione degli errori.
Locazione Procedura Hang
Error
Crash
Error
Errori
latenti
Errori da
approfondire
131c VirtualizeTimerC$0$TimerFrom$getNow 8 0 0 0
13e8 Atm128AlarmAsyncP$0$Alarm$stop 0 0 0 32
140e VirtualizeTimerC$0$TimerFrom$startOneShotAt 32 0 0 0
14c4 AlarmToTimerC$0$Timer$startOneShotAt 0 0 8 0
18b4 VirtualizeTimerC$0$Timer$fired 13 15 0 4
1942 BlinkC$Timer1$fired 3 5 0 0
1cee Atm128AlarmAsyncP$0$setInterrupt 0 0 8 24
1f40 AlarmToTimerC$0$fired$runTask 8 0 0 0
Figura 5.15: Grafico a torta che riporta i risultati degli esperimenti di iniezione in memoria
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
119
20b2 VirtualizeTimerC$0$Timer$startPeriodic 0 0 8 0
2178 __vector_15 0 0 48 0
219c __vector_15 8 0 0 0
21ec HplAtm128Timer0AsyncP$Compare$fired 0 0 48 0
2248 Atm128AlarmAsyncP$0$Compare$fired 0 0 25 23
81c HplAtm128GeneralIOPinP$31$IO$set 0 0 0 8
Analizziamo in maggior dettaglio lo studio di fault injection relativo alla locazione 140e in
cui sono rilevati tutti errori di tipo Hang. Quindi riportiamo una porzione di codice della
procedura VirtualizeTimerC$0$TimerFrom$startOneShotAt che contiene la locazione
140e di interesse:
1408: 0f 93 push r16
140a: 1f 93 push r17 140c: cf 93 push r28 140e: df 93 push r29 1410: cd b7 in r28, 0x3d ; 61 1412: de b7 in r29, 0x3e ; 62 1414: 28 97 sbiw r28, 0x08 ; 8 1416: 0f b6 in r0, 0x3f ; 63 1418: f8 94 cli 141a: de bf out 0x3e, r29 ; 62 141c: 0f be out 0x3f, r0 ; 63 141e: cd bf out 0x3d, r28 ; 61 1420: 69 83 std Y+1, r22 ; 0x01 1422: 7a 83 std Y+2, r23 ; 0x02 1424: 8b 83 std Y+3, r24 ; 0x03
In questo caso l’iniezione del fault modifica uno dei bit del registro r29 prima che il suo
contenuto venga salvato nello stack. Questo salvataggio viene effettuato per non
modificare il valore originario contenuto nel registro in quanto all’interno della procedura
viene utilizzato il registro r29 modificandone il valore. Inoltre il fault con molta
probabilità sarà attivato nel momento in cui verrà ripristinato nel registro r29 il valore
salvato nello stack. Si verificano degli errori di tipo Hang in quanto è possibile che il
valore del registro r29 all’interno della procedura chiamante sia utilizzato per il calcolo di
Tabella 5.8: Parametri utilizzati per la campagna di fault injection in memoria e outcome
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
120
una condizione di terminazione di un ciclo. A rafforzare la nostra ipotesi c’è anche il
valore di latenza riscontrato che è di 1724 cicli macchina.
Di seguito approfondiamo lo studio di fault injection relativo alla locazione 21ec
riportando il codice della procedura HplAtm128Timer0AsyncP$Compare$fired:
21ec: cf 93 push r28
21ee: df 93 push r29 21f0: cd b7 in r28, 0x3d ; 61 21f2: de b7 in r29, 0x3e ; 62 21f4: 0e 94 ff 10 call 0x21fe 21f8: df 91 pop r29 21fa: cf 91 pop r28 21fc: 08 95 ret
In questo caso l’iniezione del fault modifica un bit del registro r28 prima che il suo
contenuto venga salvato all’interno dello stack. In base agli esperimenti di fault injection
eseguiti sono stati rilevati tutti errori latenti in quanto con molta probabilità la procedura
chiamante modifica il registro r28 senza utilizzare il valore contenuto.
Nel grafico successivo riportiamo le percentuali degli errori di Crash ed Hang che si sono
verificati nel corso dei 328 esperimenti in funzione dei cicli di latenza riscontrati.
Figura 5.16: Latenza relativa all’iniezione in memoria
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
121
Dall’istogramma si nota che il 64% degli errori (tipo Crash ed Hang) ha una latenza che
supera i 160 cicli macchina. In particolare per gli errori di tipo Hang il valore massimo di
latenza riscontrato è di 1724 cicli macchina mentre per quelli di tipo Crash è di 614 cicli
macchina (per questo tipo di errori la latenza minima è nulla). Inoltre se confrontiamo
questo istogramma con quello di figura 5.4 (istogramma della latenza degli errori in
memoria di Mantis OS), notiamo la presenza degli errori di tipo Hang e l’aumento della
latenza per gli errori di tipo Crash.
5.2.3 PC Error Injection
Il grafico a torta sottostante riporta i risultati della campagna di fault injection ottenuti,
attraverso l’utilizzo dell’AVR-INJECT Tool, iniettando guasti nel registro PC. In
particolare sono stati realizzati 280 esperimenti raccolti in 13 studi step-by-step. E’
interessante notare che per questa tipologia di iniezione gli errori rilevati sono tutti di tipo
Crash.
Figura 5.17: Grafico a torta che riporta i risultati degli esperimenti di iniezione nel registro PC
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
122
Questo risultato, come già spiegato nel paragrafo relativo all’iniezione nel codice di
Mantis OS, non ci meraviglia in quanto è dovuto alla particolare iniezione effettuata.
Infatti quando viene modificato il contenuto del registro PC ci sono solamente due
possibilità: o l’indirizzo ottenuto non è valido e viene quindi rilevato un Crash error
oppure l’indirizzo ottenuto è valido e si effettua il salto ad un’altra porzione di codice. Nel
nostro caso, in tutti gli esperimenti di fault injection effettuati è stato ottenuto un indirizzo
non valido e quindi il microcontrollore ha bloccato l’esecuzione dell’applicazione.
Confrontando questo grafico con quello in figura 5.5 (grafico a torta dei risultati degli
esperimenti di iniezione nel registro PC in Mantis OS), notiamo l’assenza degli errori
latenti e di quelli da approfondire, questo come già spiegato è da attribuire agli indirizzi
non validi ottenuti in seguito all’iniezione del fault.
Nella tabella seguente riportiamo le locazioni generate in modo casuale dal tool con le
relative procedure, il numero di esperimenti di fault injection eseguiti per ognuna di esse e
i tipi di errori rilevati.
Locazione Procedura Hang
Error
Crash
Error
Errori
latenti
Errori da
approfondire
1006 HplCC1000P$HplCC1000$write 0 8 0 0
12e __nesc_atomic_end 0 8 0 0
143a VirtualizeTimerC$0$TimerFrom$startOneShotAt 0 32 0 0
14e6 AlarmToTimerC$0$start 0 32 0 0
1536 AlarmToTimerC$0$start 0 8 0 0
16a6 Atm128AlarmAsyncP$0$TimerCtrl$getInterruptFlag 0 16 0 0
1834 VirtualizeTimerC$0$fireTimers 0 32 0 0
1876 VirtualizeTimerC$0$Timer$fired 0 24 0 0
1ad2 SchedulerBasicP$TaskBasic$postTask 0 16 0 0
1b0c SchedulerBasicP$pushTask 0 40 0 0
21c8 HplAtm128Timer0AsyncP$stabiliseTimer0 0 48 0 0
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
123
72a HplAtm128GeneralIOPinP$6$IO$makeInput 0 8 0 0
fe __nesc_atomic_start 0 8 0 0
Di seguito riportiamo il grafico con le percentuali di occorrenza degli errori di Crash ed
Hang che si sono verificati nel corso dei 280 esperimenti di fault injection in funzione dei
cicli di latenza riscontrati.
Dall’istogramma si nota che tutti gli errori hanno una latenza che non supera i 60 cicli (in
particolare il valore di latenza riscontrato è nullo). In questo caso confrontando
l’istogramma con quello di figura 5.6 (relativo alla latenza degli esperimenti di fault
injection nel registro PC in Mantis OS) notiamo che sono perfettamente identici.
5.2.4 SP Error Injection
Il grafico di figura 5.19 mostra i risultati della campagna di fault injection ottenuti,
attraverso l’utilizzo dell’AVR-INJECT Tool, iniettando guasti nel registro SR. In
Tabella 5.9: Parametri utilizzati per la campagna di fault injection nel registro PC e outcome
Figura 5.18: Latenza relativa all’iniezione nel registro PC
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
124
particolare sono stati realizzati 296 esperimenti raccolti in 30 studi step-by-step. Dal
grafico si nota come la percentuale di occorrenza maggiore è quella relativa agli errori di
tipo Hang con il 57,3%.
Confrontando questo grafico con quello in figura 5.7 (grafico a torta dei risultati degli
esperimenti di iniezione nel registro SP in MantisOS), notiamo che la percentuale degli
errori da approfondire è notevolmente diminuita mentre quella degli errori di tipo Hang è
aumentata di molto. Questa osservazioni non ci permette particolari spunti di riflessione in
quanto entrambe le tipologie di errore presentano soltanto aspetti negativi. Tuttavia
sempre dal confronto possiamo notare che la percentuale di occorrenza degli errori di tipo
Crash è diminuita molto (passando dal 62,1% di Mantis al 39,0% di TinyOS) e che sono
proprio assenti gli errori latenti. L’assenza degli errori latenti ci permette di dire che,
relativamente all’iniezione dei fault nel registro SP, Mantis OS in un certo senso è più
robusto di TinyOS (infatti non è possibile escludere che gli errori latenti possono essere
Figura 5.19: Grafico a torta che riporta i risultati degli esperimenti di iniezione nel registro SP
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
125
attivati successivamente). Invece la diminuzione della percentuale di occorrenza per gli
errori di tipo Crash ci porta ad affermare che, relativamente all’iniezione dei fault nel
registro SP, Mantis OS è in un certo senso più “safe” di TinyOS.
Riportiamo di seguito una tabella contenente le locazioni generate dal tool con le rispettive
procedure, il numero di esperimenti di fault injection realizzati per ognuna di esse e gli
errori riscontrati.
Locazione Procedura Hang
Error
Crash
Error
Errori
latenti
Errori da
approfondire
117a SchedulerBasicP$Scheduler$runNextTask 6 2 0 0
12e2 VirtualizeTimerC$0$TimerFrom$getNow 5 3 0 0
1336 AlarmToTimerC$0$Timer$getNow 5 2 0 1
140 __nesc_atomic_end 6 2 0 0
1468 AlarmToTimerC$0$Timer$startOneShotAt 5 3 0 0
15bc Atm128AlarmAsyncP$0$Counter$get 6 2 0 0
16ac Atm128AlarmAsyncP$0$TimerCtrl$getInterruptFlag 7 1 0 0
16b4 HplAtm128Timer0AsyncP$TimerCtrl$getInterruptFlag 4 4 0 0
16c8 Atm128AlarmAsyncP$0$Compare$get 4 4 0 0
1706 HplAtm128Timer0AsyncP$Compare$get 5 3 0 0
170e Atm128AlarmAsyncP$0$Timer$get 4 4 0 0
1852 VirtualizeTimerC$0$Timer$fired 3 5 0 0
20b2 VirtualizeTimerC$0$Timer$startPeriodic 4 3 0 1
219c __vector_15 5 3 0 0
21aa __vector_15 3 5 0 0
21bc __vector_15 3 5 0 0
21c4 HplAtm128Timer0AsyncP$stabiliseTimer0 3 5 0 0
248 RealMainP$Scheduler$init 5 2 0 1
4cc LedsP$Init$init 4 3 0 1
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
126
7da HplAtm128GeneralIOPinP$28$IO$set 5 3 0 0
808 HplAtm128GeneralIOPinP$31$IO$set 5 3 0 0
8b0 HplAtm128GeneralIOPinP$15$IO$makeInput 5 2 0 1
8f6 HplAtm128GeneralIOPinP$11$IO$makeInput 4 3 0 1
940 ecombine 16 15 0 1
98a PlatformP$power_init 4 3 0 1
9c8 RealMainP$SoftwareInit$init 6 1 0 1
b1e HplAtm128Timer0AsyncP$Compare$start 3 3 0 2
d2 __nesc_atomic_start 25 15 0 0
fc6 SchedulerBasicP$TaskBasic$runTask 4 4 0 0
b72 __nesc_enable_interrupt 5 3 0 0
Dalla tabella si nota che la variabilità degli errori rispetto alla variazione del bit-flip e del
ciclo di iniezione è maggiore rispetto agli altri casi. Analizziamo di seguito un caso
notevole in cui c’è variabilità rispetto al bit-flip. Riportiamo di seguito una porzione di
codice relativa alla procedura SchedulerBasicP$TaskBasic$runTask che contenga la
locazione fc6:
fbc: 0f b6 in r0, 0x3f ; 63
fbe: f8 94 cli fc0: de bf out 0x3e, r29 ; 62 fc2: 0f be out 0x3f, r0 ; 63 fc4: cd bf out 0x3d, r28 ; 61 fc6: df 91 pop r29 fc8: cf 91 pop r28 fca: 08 95 ret
In questo tipo di iniezione viene modificato un bit del registro SP, questo comporta che le
successive istruzioni che utilizzano lo stack possono o sovrascrivere delle locazioni già
utilizzate oppure prelevare dallo stack valori sbagliati. Un errore di tipo Crash si verifica
nel momento in cui la procedura in esame restituisce il controllo al chiamante e l’indirizzo
di ritorno prelevato dallo stack non è un indirizzo valido. Invece un errore di tipo Hang si
Tabella 5.10: Parametri utilizzati per la campagna di fault injection nel registro SP e outcome
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
127
può verificare quando la procedura in esame restituisce il controllo al chiamante e
l’indirizzo di ritorno prelevato dallo stack anche se valido non è quello corretto.
Si riporta di seguito il grafico con le percentuali di occorrenza degli errori di Crash ed
Hang in funzione dei cicli di latenza riscontrati.
Dall’istogramma si nota che la maggioranza degli errori (circa l’80%) ha una latenza che
non supera i 100 cicli macchina. Inoltre rispetto all’istogramma in figura 5.8 (relativo alla
latenza negli esperimenti in MantisOS nel registro SP) notiamo la diminuzione della
latenza per gli errori di tipo Hang (infatti in questo caso più del 40% di essi ha una latenza
che non supera i 100 cicli macchina). In particolare per quanto riguarda gli errori di tipo
Hang il valore massimo di latenza riscontrato è di 6076 cicli macchina mentre per quelli di
tipo Crash il valore massimo di latenza riscontrato è di 180000 cicli macchina (di tratta
tuttavia di un caso isolato infatti se si esclude questo valore la latenza più alta riscontrata è
di 391 cicli macchina).
Figura 5.20: Latenza relativa all’iniezione nel registro SP
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
128
5.2.5 SR Error Injection
Riportiamo di seguito il grafico a torta che mostra i risultati della campagna di fault
injection ottenuti, attraverso l’utilizzo dell’AVR-INJECT Tool, iniettando guasti nel
registro SR. In particolare sono stati realizzati 304 esperimenti di fault injection raccolti in
14 studi step-by-step. Dal grafico si nota che gli errori rilevati sono quasi tutti errori latenti
(92,1%), questo risultato è strettamente legato al tipo di iniezione effettuata. Infatti nel
caso specifico il fault iniettato modifica uno dei bit del registro SR che con molta
probabilità non è quello utilizzato dall’istruzione target (istruzione in cui si inietta il fault),
inoltre dato che l’esecuzione di quasi tutte le istruzioni del microcontrollore modifica uno
o più bit del registro SR è possibile che già dopo poche istruzioni venga annullato l’effetto
del fault.
Confrontando questo grafico con quello in figura 5.9 (grafico a torta dei risultati degli
esperimenti di iniezione nel registro SR in Mantis OS), notiamo che la percentuale di
occorrenza degli errori da approfondire è notevolmente diminuita mentre quella degli
errori di tipo Hang è diventata completamente nulla. Inoltre un aspetto molto importante è
Figura 5.21: Grafico a torta che riporta i risultati degli esperimenti di iniezione nel registro SR
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
129
il considerevole aumento degli errori latenti (si passa dal 55,3% di Mantis al 92,1% di
TinyOS) questo ci porta ad affermare che, relativamente all’iniezione nel registro SP,
TinyOS è in qualche modo più robusto di Mantis OS.
Nella tabella seguente sono riportate le locazioni generate dal tool con le relative
procedure, il numero di esperimenti di fault injection eseguiti per ognuna di esse e i tipi di
errori riscontrati.
Locazione Procedura Hang
Error
Crash
Error
Errori
latenti
Errori da
approfondire
1000 HplCC1000P$HplCC1000$write 0 0 16 0
1450 VirtualizeTimerC$0$TimerFrom$startOneShotAt 0 0 32 0
1784 VirtualizeTimerC$0$fireTimers 0 0 8 0
1996 HplAtm128GeneralIOPinP$IO$toggle 0 0 8 0
1bce Atm128AlarmAsyncP$0$Alarm$startAt 0 0 32 0
1cda Atm128AlarmAsyncP$0$setInterrupt 0 0 8 0
1da2 Atm128AlarmAsyncP$0$setInterrupt 0 0 48 0
1e2c Atm128AlarmAsyncP$0$setOcr0 0 8 0 0
1e68 Atm128AlarmAsyncP$0$TimerAsync$compareBusy 0 0 32 0
20a6 VirtualizeTimerC$0$Timer$startPeriodic 0 0 24 0
20f2 VirtualizeTimerC$0$startTimer 0 0 24 0
2232 Atm128AlarmAsyncP$0$Compare$fired 0 0 48 0
ec2 mcombine 0 0 0 8
f26 SchedulerBasicP$popTask 0 0 0 8
E’ interessante analizzare lo studio in cui sono stati rilevati errori di tipo Crash. Quindi di
seguito riportiamo una porzione di codice della procedura
Atm128AlarmAsyncP$0$setOcr0 che contiene al suo interno la locazione 1e2c:
Tabella 5.11: Parametri utilizzati per la campagna di fault injection nel registro SR e outcome
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
130
1e22: b0 91 26 01 lds r27, 0x0126
1e26: 28 17 cp r18, r24 1e28: 39 07 cpc r19, r25 1e2a: 4a 07 cpc r20, r26 1e2c: 5b 07 cpc r21, r27 1e2e: 50 f4 brcc .+20 ; 0x1e44 1e30: 80 91 23 01 lds r24, 0x0123 1e34: 90 91 24 01 lds r25, 0x0124
In questo caso l’errore di tipo Crash è conseguenza di un valore di indirizzo non valido.
Infatti l’istruzione successiva a quella target (cpc r21,r27 ) è un’istruzione di salto relativo
condizionato che invece di essere eseguita all’interno della procedura viene eseguita nel
blocco di InstructionTarget e questo provoca la generazione di un indirizzo non valido. Di
seguito analizziamo in dettaglio lo studio di fault injection relativo alla locazione 20f2
riportando una porzione di codice della procedura VirtualizeTimerC$0$startTimer :
20ec: 33 27 eor r19, r19
20ee: c9 01 movw r24, r18 20f0: 88 0f add r24, r24 20f2: 99 1f adc r25, r25 20f4: 88 0f add r24, r24 20f6: 99 1f adc r25, r25 20f8: 88 0f add r24, r24 20fa: 99 1f adc r25, r25 20fc: 82 0f add r24, r18 20fe: 93 1f adc r25, r19 2100: 80 50 subi r24, 0x00 ; 0 2102: 9f 4f sbci r25, 0xFF ; 255 2104: 9a 83 std Y+2, r25 ; 0x02 2106: 89 83 std Y+1, r24 ; 0x01 2108: e9 81 ldd r30, Y+1 ; 0x01
In questo caso anche se il contenuto del registro r25 può subire delle modifiche in seguito
all’iniezione effettuata (qualora in seguito all’iniezione viene modificato proprio il bit C
del registro SR) non sono presenti all’interno della procedura in esame istruzioni di salto
condizionato che diversificano il flusso di esecuzione. Quindi è per questo motivo che tutti
gli errori rilevati, in riferimento alla locazione 20f2, sono errori latenti.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
131
Nel grafico successivo riportiamo le percentuali degli errori di Crash ed Hang che si sono
verificati durante i 304 esperimenti di fault injection in base ai cicli di latenza riscontrati.
Dalla tabella 5.11 notiamo che su 304 esperimenti di fault injection si sono verificati
soltanto 8 casi di errori latenti (tutti nella locazione 1e2c e con latenza nulla). Inoltre
rispetto all’istogramma di figura 5.10 (relativo alla latenza negli esperimenti di fault
injection in MantisOS nel registro SR) notiamo l’assenza di errori di tipo Hang.
5.2.6 TinyOS Total Error Injection
Di seguito riportiamo il grafico a torta che raggruppa i risultati delle campagne di fault
injection, ottenuti attraverso l’utilizzo dell’AVR-INJECT Tool, effettuando le differenti
tipologie di iniezione. In particolare sono stati realizzati un totale di 1520 esperimenti
raccolti in 84 studi step-by-step. Dal grafico si nota che le percentuali di occorrenza
Figura 5.22: Latenza relativa all’iniezione nel registro SR
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
132
maggiori sono relative agli errori di tipo Crash con il 34,5% e a quelli latenti con il 32,2%.
Seguono gli errori di tipo Hang con il 22,2% ed infine quelli da approfondire con solo
l’11,1% .
Rispetto al grafico di figura 5.11 (che riporta i risultati totali in Mantis OS) non possiamo
fare grandi considerazioni in quanto mentre diminuisce la percentuale di occorrenza degli
errori da approfondire allo stesso tempo aumenta quella degli errori di tipo Hang, infatti
queste due categorie di errori presentano soltanto aspetti negativi. Invece le percentuali di
occorrenza delle altre due categorie di errori restano pressoché invariate.
Nel grafico successivo riportiamo le percentuali degli errori, di tipo Crash ed Hang, che si
sono verificati nel corso dei 1520 esperimenti in funzione dei cicli di latenza riscontrati.
Figura 5.23: Grafico a torta che riporta i risultati globali degli esperimenti di iniezione.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
133
Dall’istogramma si nota che la percentuale degli errori di tipo Crash è più grande di quella
degli errori di tipo Hang. Inoltre mentre per gli errori di tipo Hang la latenza varia in un
range abbastanza ampio (da un valore minimo di 70 cicli ad un valore massimo di 6076
cicli macchina), nel caso di errori di tipo Crash il 52% ha una latenza che non supera i 60
cicli macchina (il valore minimo riscontrato è nullo mentre quello massimo escludendo il
caso isolato è di 614 cicli).
5.3 Risultati ottenuti con l’applicazione surge
Per dimostrare la generalità dell’AVR-INJECT Tool abbiamo deciso di effettuare alcuni
esperimenti di fault injection in una differente applicazione; è stata scelta l’applicazione
surge in quanto è un’applicazione tipica per le reti di sensore senza filo. In pratica questa
applicazione effettua delle misurazioni ed invia dei messaggi contenenti i valori ricavati.
Figura 5.24: Latenza totale
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
134
Visto che la campagna di fault injection da realizzare serve solo per dimostrare la
generalità del tool verranno effettuati soltanto 16 esperimenti (distribuiti uniformemente in
due studi) per ogni tipologia di iniezione. Quindi presentiamo direttamente i risultati totali
ottenuti sia per Mantis OS che per TinyOS.
5.3.1 Risultati totali in Mantis OS
Di seguito riportiamo il grafico a torta che riporta le percentuali di occorrenza delle
quattro tipologie di errori. In particolare sono stati realizzati 80 esperimenti di fault
injection raccolti in 10 studi step-by-step. Dal grafico si nota che la percentuale di
occorrenza maggiore è quella relativa agli errori da approfondire con il 55%.
Confrontando questo grafico con quello di figura 5.11 (che riporta i risultati totali ottenuti
in seguito agli esperimenti di fault injection effettuati sull’applicazione blink_led di
Mantis OS) notiamo l’assenza degli errori latenti. Tuttavia questo risultato dipende dal
Figura 5.25: Grafico a torta che riporta i risultati globali dell’iniezione
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
135
ridotto numero di esperimenti eseguiti (infatti sono stati realizzati soltanto 80 esperimenti
di fault injection rispetto ai 1752 eseguiti sull’applicazione blink_led). Invece restano
pressoché invariate le percentuali di occorrenza degli errori di tipo Crash ed Hang.
Per completezza di seguito riportiamo in forma tabellare le locazioni generate dal tool con
le rispettive procedure, il numero di esperimenti di fault injection eseguiti per ognuna di
esse con i tipi di errori rilevati.
Locazione Procedura Hang
Error
Crash
Error
Errori
latenti
Errori da
approfondire
1c8e com_send_IFACE_RADIO 0 0 0 8
517e dispatcher 0 0 0 8
55f8 mos_thread_wakeup_noints 0 8 0 0
612a set_alarm_timer 0 0 0 8
2cba mica2_sounder_init 0 8 0 0
64a0 __vector_12 0 8 0 0
5dce mos_sem_post 5 3 0 0
6f2c __prologue_saves 0 4 0 4
59a4 mos_sched_start 0 0 0 8
6e42 __udivmodsi4_ep 0 0 0 8
Nella tabella sono riportate le locazioni utilizzate in tutte le diverse tipologie di iniezione,
in particolare le prime due locazione sono relative all’iniezione nel codice, la terza e la
quarta locazione sono relative all’iniezione in memoria, la quinta e la sesta locazione sono
relative all’iniezione nel registro PC, la settima e l’ottava locazione sono relative
all’iniezione nel registro SP ed infine le ultime due locazioni sono relative all’iniezione nel
registro SR.
Tabella 5.12: Parametri globali utilizzati per la campagna di fault injection e outcome
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
136
Mostriamo di seguito le percentuali di occorrenza per gli errori di tipo Crash ed Hang al
variare dei cicli di latenza riscontrati.
Se confrontiamo questo grafico con quello di figura 5.12 (grafico della latenza totale in
Mantis riferito all’applicazione blink_led) notiamo una minore variabilità del valore di
latenza, tuttavia anche questo comportamento è da attribuirsi al ridotto numero di
esperimenti di fault injection eseguiti.
5.3.2 Risultati totali in TinyOS
Il seguente grafico a torta riporta le percentuali di occorrenza delle quattro tipologie di
errori. In particolare sono stati realizzati 80 esperimenti di fault injection raccolti in 10
studi step-by-step. Dal grafico si nota che gli errori di tipo Crash hanno la percentuale di
occorrenza maggiore con il 35% seguiti da quelli latenti con il 28,8%.
Figura 5.26: Latenza globale
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
137
Se confrontiamo questo grafico con quello di figura 5.23 (grafico che riporta i risultati
globali dell’iniezione nell’applicazione Blink di TinyOS ) notiamo che le percentuali di
occorrenza delle quattro tipologie di errori differiscono di poco, questo significa che il
ridotto numero di esperimenti eseguiti ha influito meno rispetto al caso precedente.
Per completezza di seguito mostriamo una tabella che riporta le locazioni generate dal tool
con le relative procedure, il numero di esperimenti eseguiti per ognuna di esse e i tipi di
errori riscontrati.
Locazione Procedura Hang Error Crash
Error
Errori
latenti
Errori da
approfondire
225c memset 0 8 0 0
558 main 1 0 0 7
1ba2 main 0 0 0 8
1e0e main 0 0 7 1
1b96 main 0 8 0 0
Figura 5.27: Grafico a torta che riporta i risultati globali dell’iniezione
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
138
37c __vector_15 0 8 0 0
328 __vector_15 6 2 0 0
520 __vector_15 6 2 0 0
1c9a main 0 0 8 0
1efe main 0 0 8 0
Anche in questo caso nella tabella sono riportate le locazioni utilizzate in tutte le diverse
tipologie di iniezione, in particolare vale il principio di classificazione descritto nel
paragrafo precedente.
Di seguito riportiamo il grafico che contiene la percentuale di occorrenza per gli errori di
tipo Crash ed Hang al variare dei cicli di latenza riscontrati.
Se confrontiamo questo grafico con quello di figura 5.24 (grafico della latenza totale
relativa agli esperimenti di fault injection sull’applicazione Blink di TinyOS) notiamo una
minore variabilità dei cicli di latenza ed anche una loro riduzione sia per gli errori di tipo
Tabella 5.13: Parametri globali utilizzati per la campagna di fault injection e outcome
Figura 5.28: Latenza globale
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
139
Crash che per quelli di tipo Hang. Tuttavia i risultati ottenuti non possono essere ritenuti
significativi a causa del ridotto numero di esperimenti di fault injection eseguiti.
5.4 TinyOS vs Mantis OS
In base ai risultati ottenuti attraverso la campagna di fault injection possiamo mettere in
evidenza alcune caratteristiche dei due sistemi operativi.
Iniziamo confrontando due moduli simili dei due sistemi operativi: il dispatcher di Mantis
e lo scheduler di TinyOS. Di seguito riportiamo una tabella che contiene le percentuali di
occorrenza degli errori che sono stati riscontrati durante gli esperimenti di fault injection
concentrati in questi due moduli.
Hang Error Crash Error Errori latenti Errori da
approfondire
Dispatcher
(Mantis)
0,0% 17,2% 69,0% 13,8%
Scheduler
(TinyOS)
38,2% 55,6% 0,0% 6,2%
In base ai valori della tabella possiamo dire che il dispatcher di Mantis OS è più robusto
rispetto allo scheduler di TinyOS anche se quest’ultimo è in un certo senso più “safe” visto
che la percentuale degli errori di tipo Crash è tre volte superiore.
Riportiamo di seguito i risultati ottenuti effettuando un’analisi analoga su due coppie di
procedure simili: mos_mutex_lock e mos_mutex_unlock di Mantis OS e nesc_atomic_star
e nesc_atomic_end di TinyOS.
Tabella 5.14: Percentuali errori per il confronto tra scheduler e dispatcher
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
140
Hang Error Crash Error Errori latenti Errori da
approfondire
mos_mutex_lock
mos_mutex_unlock
0,0% 96,9% 3,1% 0,0%
nesc_atomic_start
nesc_atomic_end
38,7% 42,5% 0,0% 18,8%
In base ai valori della tabella possiamo affermare che, relativamente all’iniezione dei fault
nelle due coppie di procedure, Mantis è in un certo senso più “safe” di TinyOS (infatti la
percentuale di occorrenza degli errori di tipo Crash in Mantis è doppia rispetto a quella di
TinyOS) ed anche più robusto in quanto si sono verificati alcuni casi di errori latenti.
Inoltre se consideriamo l’iniezione nel registro SP, notiamo che in Mantis OS abbiamo il
62,1% di errori di tipo Crash con solo il 5,7% di errori di tipo Hang mentre in TinyOS
abbiamo il 57,3% di errori di tipo Hang con il 39% di errori di tipo Crash. Questo
comportamento è causato dalla differente struttura dei due sistemi operativi, in particolare
essendo Mantis un sistema operativo multithread associa uno stack ad ogni thread
effettuando dei controlli sui suoi limiti, quindi l’iniezione di un fault nel registro SP spesso
porta a violare i limiti impostati allo stack generando un errore di tipo Crash. Un altro
punto a favore di Mantis OS è la minore latenza degli errori relativi alla fault injection in
memoria, infatti in questo modo è possibile sia bloccare in anticipo l’esecuzione
dell’applicazione riducendo il consumo energetico del sensore e sia permettere ad un
eventuale detector di intervenire più tempestivamente. Tuttavia un punto a favore di
TinyOS è la minore percentuale di errori da approfondire, infatti questa tipologia di errori
richiede per l’interpretazione un’elaborazione aggiuntiva. In particolare gli errori da
approfondire possono provocare malfunzionamenti di natura diversa: di valore (ad
esempio accensione di un led sbagliato oppure invio di una misurazione errata), di
omissione (ad esempio il mancato invio di un messaggio) e bizantini. Di seguito come
Tabella 5.15: Percentuali errori per il confronto tra coppie di procedure
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
141
caso notevole riportiamo due errori da approfondire (uno relativo a TinyOS e l’altro a
Mantis OS) che hanno provocato un malfunzionamento di valore (sequenza di accensione
dei led sbagliata).
Per l’applicazione blink_led di Mantis OS la sequenza di accensione dei led corretta,
nell’intervallo temporale di 2 secondi, è: Yellow: on Green: on Red: on Yellow: off Green: off Red: off Yellow: on Green: on Red: on Red: off Red: on Red: off Red: on Red: off Red: on Red: off Red: on Red: off
Invece per l’errore da approfondire relativo all’iniezione nel codice alla locazione 284,
otteniamo la seguente sequenza di accensione: Yellow: on Green: on Red: on Yellow: off Green: off Red: off Yellow: on Green: on Red: on Yellow: off Red: off Red: on Red: off Red: on Red: off Red: on Red: off Red: on Red: off
in cui si nota l’errato spegnimento del led giallo.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
142
Per l’applicazione blink di TinyOS la sequenza di accensione dei led corretta,
nell’intervallo temporale di 2 secondi, è: Red: on Green: on Yellow: on Red: off Green: off Yellow: off Red: on Red: off Green: on Red: on
Invece per l’errore da approfondire relativo all’iniezione in memoria alla locazione 18b4,
otteniamo la seguente sequenza di accensione: Red: on Green: on Yellow: on Red: off Green: off Yellow: off Red: on Green: on Yellow: on Red: off Yellow: off Red: on Yellow: on
in cui notiamo la non corretta accensione dei led verde e giallo.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
143
Conclusioni
Il presente lavoro di tesi nasce dall’esigenza di utilizzare l’AVR-INJECT Tool, realizzato
da Testa nel suo lavoro di tesi [9], come strumento per valutare la robustezza ai guasti di
sistemi operativi differenti. Per fare ciò c’è la necessità di automatizzare la fase di analisi
dei risultati del tool.
Il lavoro è iniziato partendo da uno studio accurato del tool che ha permesso la rilevazione
e la correzione di alcuni problemi. Successivamente sono state ampliate le sue
funzionalità, in particolare è stata introdotta la possibilità di iniettare guasti all’interno del
registro Stack Pointer (SP) ed è stato automatizzato il processo di analisi dei risultati
(questo processo in modo automatico effettua sia la classificazione che la generazione dei
grafici dei risultati).
Nella seconda parte del lavoro di tesi, il tool modificato è stato utilizzato come strumento
per la realizzazione di un’analisi comparativa tra TinyOS e Mantis.
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
144
Sviluppi futuri
Tra i possibili sviluppi futuri possiamo individuare la modifica del tool per realizzare
campagne di fault injection su sensori reali attraverso l’utilizzo dell’interfaccia JTAG.
Un altro miglioramento possibile potrebbe essere l’aggiunta di nuove tipologie di guasti
come: stuck-at e software faults.
Un altro possibile sviluppo futuro può riguardare la generazione dei parametri per lo studio
di tipo random. Infatti al momento il tool genera valori casuali seguendo una distribuzione
di tipo uniforme. L’idea è quella di introdurre anche una distribuzione gaussiana: l’utente
in tal caso dovrà fornire due parametri, media e varianza (µ, σ).
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
145
Bibliografia
[1] E. Sisinni Reti wireless di sensori: problematiche e recenti sviluppi
[2] Ruiping Ma; Liudong Xing; Michel, H.E. Fault-Intrusion Tolerant Techniques in
Wireless Sensor Networks 2nd IEEE International Symposium on Volume , Issue , Sept.
2006
[3] D. Stott, P.H. Jones, M. Hamman, Z. Kalbarczyk, R.K. Iyer NFTAPE: Networked Fault
Tolerance and Performance Evaluator University of Illinois at Urbana-Champaign
[4] Robert Slater, Fault Injection, Carnegie Mellon University, Spring 1998
[5] Jeffrey Voas, Fault Injection for the Masses, Reliable Software Technologies,
December 1998
[6] Fulvio Corno, Maurizio Rebaudengo, Matteo Sonza Reorda, Tecniche per il progetto di
sistemi elettronici tolleranti ai guasti, 15-23 luglio 2002
[7] Andrea Aiello, Tecniche software per l’iniezione di guasti su microcontrollori per reti
di sensori senza filo, luglio 2007
[8] Weining Gu, Zbigniew Kalbarczyk, Ravishankar K. Iyer, Error Sensitivity of Linux
Kernel Executing on PowerPC G4 and Pentium 4 Processors, 2004
[9] Alessandro Testa, Un tool per l’iniezione di guasti in microcontrollori per Wireless
Sensor Networks, settembre 2008
[10] Shah Bhatti, James Carlson, Hui Dai, Jing Deng, Jeff Rose, Anmol Sheth, Brian
Shucker, Charles Gruenwald, Adam Torgerson, Richard Han, MANTIS OS: An Embedded
Multithreaded Operating System for Wireless Micro Sensor Platforms, agosto 2005
[11] Filippo Pacifici, Metodologie per la realizzazione di software per reti di sensori
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
146
[12] Cormac Duffy, Utz Roedig, John Herbert, Cormac Sreenan, A Comprehensive
Experimental Comparison of Event Driven and Multi-Threaded Sensor Node Operating
Systems, marzo 2008
Valutazione mediante fault injection di sistemi operativi per reti di sensori senza filo
147
Sitografia
(1) TinyOS
http://www.tinyos.net
(2) Washington Sate University Vancouver
http://www.vancouver.wsu.edu/
(3) IBM JDK
http://www.ibm.com/developerworks/java/jdk/
(4) Avrora
http://compilers.cs.ucla.edu/avrora/
(5) Eclipse
http://www.eclipse.org/
(6) Xerces
http://xerces.apache.org/
(7) Mantis
http://mantis.cs.colorado.edu/