Bachelorarbeit Automatisierte Fehlerinjektion mit dem GNU Debugger
←
→
Transkription von Seiteninhalten
Wenn Ihr Browser die Seite nicht korrekt rendert, bitte, lesen Sie den Inhalt der Seite unten
Bachelorarbeit Automatisierte Fehlerinjektion mit dem GNU Debugger Marvin Lampe 23. März 2021 Betreuer Dr.-Ing. Christoph Borchert Prof. Dr.-Ing. Olaf Spinczyk Universität Osnabrück Institut für Informatik Arbeitsgruppe Eingebettete Softwaresysteme https://ess.cs.uos.de/
Zusammenfassung Im Rahmen dieser Bachelorarbeit wurde ein GNU Debugger Fehlerinjektions-Tool ent- wickelt, zum automatisiertem evaluieren der Fehlertoleranz. Aufgrund der steigenden Empfindlichkeit der Hardware gegenüber Soft Error, wird die Fehlertoleranz zunehmend bedeutsamer. Der gewählte Ansatz wird mit dem Fehlerinjektionstool Fail* verglichen und evaluiert. Das entwickelte Tool ist zwar ungenauer als Alternative Fehlerinjektions- tools, es können aber trotzdem schnelle und aussagekräftige Ergebnisse über die Fehler- toleranz gemacht werden und da noch nicht alle möglichen Features implementiert sind hat das Tool ein großes Potential. Abstract As part of this bachelor thesis a GNU Debugger Fault Injection Tool was developed for the automated evaluation of the fault tolerance. Because of the increasing hardware vulnerability against soft errors, fault tolerance is getting progressively important. The chosen approach is compared with the Fault Injection Tool Fail*. Although the devel- oped tool is less precise than alternative fault injection tools, it can still produce quick and meaningful results about the fault tolerance and since not all possible features have yet been implemented, the tool has great potential.
Inhaltsverzeichnis 1 Einleitung 1 2 Grundlagen 3 2.1 Soft Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2 Fehlertoleranzmechanismen . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.3 Fehlerinjektionsverfahren . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.3.1 Hardware-implementierte Fehlerinjektion . . . . . . . . . . . . . 4 2.3.2 Software-implementierte Fehlerinjektion . . . . . . . . . . . . . . 4 2.3.3 Simulationsbasierte Fehlerinjektion . . . . . . . . . . . . . . . . . 4 2.3.4 Fehlerraum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.3.5 Ablauf von Fehlerinjektionstools . . . . . . . . . . . . . . . . . . 6 3 Literatur 7 4 Konzept 9 4.1 Intention . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 4.2 Konzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 4.2.1 Ergebnistypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 5 Implementierung 11 5.1 Software-Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 5.2 Golden Runs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 5.2.1 Golden Run Time . . . . . . . . . . . . . . . . . . . . . . . . . . 13 5.2.2 Golden Run Output . . . . . . . . . . . . . . . . . . . . . . . . . 13 5.3 Script Starter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 5.4 Fault Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 5.4.1 Zufällige Unterbrechungen erzeugen . . . . . . . . . . . . . . . . 15 5.4.1.1 Timer-Thread . . . . . . . . . . . . . . . . . . . . . . . 15 5.4.1.2 Separater Prozess . . . . . . . . . . . . . . . . . . . . . 15 5.4.1.3 Background Execution . . . . . . . . . . . . . . . . . . 16 5.4.2 Zufälliger Bit-Flip . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5.4.3 Fälle nach der Fehlerinjektion . . . . . . . . . . . . . . . . . . . . 17 5.4.3.1 Crash . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.4.3.2 Timeout . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.4.4 Abschluss der Fehlerinjektion . . . . . . . . . . . . . . . . . . . . 18 5.5 Auswertung erstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 5.5.1 Fehlerraumgröße . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 5.5.2 Hochgerechnete Fehlerrate . . . . . . . . . . . . . . . . . . . . . . 18 5.5.3 Konfidenzintervall . . . . . . . . . . . . . . . . . . . . . . . . . . 18 i
Inhaltsverzeichnis 5.5.4 Relativer Standardfehler . . . . . . . . . . . . . . . . . . . . . . . 19 5.5.5 Resultierende Auswertungsdatei . . . . . . . . . . . . . . . . . . 19 6 Evaluation 21 6.1 Gleichverteilung der Fehlerinjektionen . . . . . . . . . . . . . . . . . . . 21 6.2 Evaluierung der Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 6.3 Verbesserungsmöglichkeiten . . . . . . . . . . . . . . . . . . . . . . . . . 24 7 Zusammenfassung 25 Literaturverzeichnis 27 Glossar 29 Abbildungsverzeichnis 29 Tabellenverzeichnis 31 ii
1 Einleitung Durch immer kleiner werdende Strukturen der Halbleiterspeicher [1] erhöht sich deren Empfindlichkeit gegenüber elektromagnetischer Strahlung [2], [3]. Hierdurch kann es zu Fehlern im Speicher kommen, welche einer der primären Hardwareursachen für Com- putersystemabstürze ist [4], [5]. Diese Art von temporären Speicherfehlern nennt man Soft Error. Um sich vor den Auswirkungen möglicher Soft Error zu schützen, können sowohl hardware- als auch softwareseitig Fehlertoleranzmechanismen integriert werden. Indem Soft Error simuliert werden, kann die Robustheit des Computersystems, bzw. die Verbesserung durch die Fehlertoleranzmechanismen evaluiert werden. Diese Bachelorarbeit befasst sich mit der Entwicklung und Evaluation eines Fehlerinjektions- Tool mit dem GNU-Debugger. Dieses Tool ist in der Lage automatisiert Soft Error zu simulieren und anschließend die Fehlertoleranz des gegebenen Zielsystems zu bewer- ten. Hierdurch kann die Verbesserung durch softwareseitiger Fehlertoleranzmechanismen festgestellt werden. Des weiteren wird das Tool mit Fail* einem anderem Fehlerinjektions- Tool verglichen. Zunächst werden in Kapitel 2 die Grundlagen in Bezug auf Fehlerinjektions-Tools ge- schaffen. Anschließend gibt es in Kapitel 3 einen Überblick bereits bestehender Arbeiten. Darauffolgend wird in Kapitel 4 das entworfene Konzept vorgestellt, dessen Implemen- tierung in Kapitel 5 erläutert wird. Im Anschluss folgt in Kapitel 6 die Evaluation des Ansatzes, indem die Ergebnisse mit denen von Fail* verglichen werden. Im letzten Kapitel werden die Ergebnisse zusammengefasst. 1
2 Grundlagen In diesem Kapitel werden die Grundlagen zum Thema Fehlerinjektion dargestellt. Zu- nächst werden in Abschnitt 2.1 die zu simulierenden Soft Error näher betrachtet. Darauf- hin werden in Abschnitt 2.2 mögliche Fehlertoleranzmechanismen gegen die Soft Error aufgezeigt. Im letzten Abschnitt 2.3 werden die drei Varianten der Fehlerinjektionsver- fahren behandelt. 2.1 Soft Error Im Gegensatz zu permanente Fehler die zum Beispiel durch Hardwaredefekte entstehen, sind Soft Error temporäre Zustandsänderungen. Sie können aufgrund elektromagneti- scher Strahlung, wie zum Beispiel kosmischer Strahlung, bei Halbleiterspeicher auftre- ten. Durch die Strahlung ist es möglich, dass ein paar Elektronen des Speicherkonden- sators vertrieben werden, wodurch sich deren Zustand ändert. Eine logische 1 kann also zu einer 0 oder umgekehrt werden, ein Bit-Flip. Jedoch ist es möglich, durch neues beschreiben des Speichers den Fehler zu korrigieren. Hinzukommt, das sich durch dem stetig steigendem Verlangen nach mehr Speicher die Integrationsdichte erhöht und die Betriebsspannung sinkt [1]. Dies wiederum erhöht die Empfindlichkeit gegenüber elektromagnetischer Strahlung [2] und die daraus entste- henden Soft Error. Aus diesem Grund ist es umso wichtiger Computersysteme mithilfe von Fehlertoleranzmechanismen zu schützen. 2.2 Fehlertoleranzmechanismen Computersysteme können sowohl durch Hardware, als auch Software Fehlertoleranter gestaltet werden. Eine Hardwaremaßnahme wäre zum Beispiel das Hinzufügen von red- undanter Komponenten, sodass es beim Fehlerauftritt noch eine zusätzlich fehlerfreie Komponente gibt [6]. Jedoch steigen durch die zusätzliche Hardware ebenfalls Gewicht, Größe, Stromverbrauch, Kosten und die Zeit zum Entwerfen [7]. Auf Softwareseite kön- nen Fehlererkennungs- und Fehlerkorrekturverfahren wie zum Beispiel die zyklische Red- undanzprüfung CRC und der Hamming-Code hinzugefügt werden. Auch diese basieren auf Redundanz, weshalb sie sinnvoll und nicht übermäßig und unangemessen platziert werden müssen, um Overhead zu vermeiden. Zum flexiblen hinzufügen der softwaresei- tigen Fehlertoleranzmechanismen eignet sich aspektorientierte Programmierung [8]. Das in dieser Bachelorarbeit vorgestellte Tool ist ausschließlich in der Lage softwareseitige Fehlertoleranzmechanismen zu evaluieren. 3
Grundlagen 2.3 2.3 Fehlerinjektionsverfahren Um die Fehlertoleranz eines Computersystems zu testen, beziehungsweise die Verbesse- rung durch Fehlertoleranzmechanismen zu evaluieren, werden Soft Error simuliert. Hier- für gibt es drei unterschiedliche Fehlerinjektionsverfahren, welche in diesem Abschnitt betrachtet werden. 2.3.1 Hardware-implementierte Fehlerinjektion Eine Variante der Hardware-implementierten Fehlerinjektion ist der Strahlungstest. Hierbei wird das zu testende Computersystem starker Ionenstrahlung ausgesetzt um einen Soft Error zu provozieren [9]. Dadurch wird der Fehler zwar sehr genau nachge- ahmt, jedoch sind durch das zufällige Auftreten die Wiederholbarkeit und die Kontrol- lierbarkeit gering. Des weiteren ist die Beschaffung und der Umgang mit den strahlungs- aktiven Materialien sehr aufwendig und teuer [10]. Alternativ zu den Strahlungstests können Soft Error direkt über die Hardware injiziert werden. Hierzu werden zum Beispiel spezielle Testzugriffspunkte oder externe Sonden, die mit den Pins der CPU verbunden sind, verwendet. Die Wiederhol- und Kontrol- lierbarkeit sind bei diesem Verfahren deutlich besser im Vergleich zum Strahlungstest, dies jedoch auf Kosten der limitierten Injektionszeit durch die Zugriffspunkte und die begrenzte Erreichbarkeit des injizierbaren Zustands [11]. 2.3.2 Software-implementierte Fehlerinjektion In diesem Verfahren wird durch Software ein Fehler, entweder vor oder während der Laufzeit, ins Zielsystem injiziert. Dieses Vorgehen ist deutlich kostengünstiger im Ver- gleich zur Hardware-implementierten Fehlerinjektion, jedoch ist die Erreichbarkeit des injizierbaren Zustandes limitierter. Zudem kann der Sondeneffekt auftreten. Das be- deutet, dass sich das Zielsystem durch die hinzugefügte Software anders verhält als im Normalfall. 2.3.3 Simulationsbasierte Fehlerinjektion Die simulationsbasierte Fehlerinjektion ist die Variante, die in dieser Bachelorarbeit und in dem Vergleichstool Fail* [11] verwendet wird. Hier werden Fehler in simulierter Hardware injiziert. Der größte Nachteil an diesem Verfahren ist die Geschwindigkeit aufgrund der aufwendigen Simulation. Je höher der Detailgrad des Simulator, desto höher ist die Erreichbarkeit des injizierbaren Zustandes, aber desto niedriger ist die Geschwindigkeit. Darüber hinaus ist dieser Ansatz kostengünstig und bietet ebenfalls eine gute Wiederhol- und Kontrollierbarkeit. Ein weiterer bedeutender Vorteil ist, dass die Fehlerinjektionen auf jeder verfügbaren Hardware durchgeführt werden können [11]. 2.3.4 Fehlerraum Der Fehlerraum beinhaltet jeden möglichen Zeitpunkt und Ort an dem ein Fehler mit- hilfe von Software injiziert werden kann. Die Abbildung 2.1 stellt den Fehlerraum dar. 4
2.3 Grundlagen … ... 5 4 Speicherbits 3 ... 2 1 1 2 3 4 5 6 7 8 9 ... CPU Zyklen Abbildung 2.1: Fehlerraum … ... 5 4 Speicherbits 3 ... 2 1 1 2 3 4 5 6 7 8 9 ... CPU Zyklen Abbildung 2.2: vollständige Fehlerraumabdeckung … ... 5 4 Speicherbits 3 ... 2 1 1 2 3 4 5 6 7 8 9 ... CPU Zyklen Abbildung 2.3: Fehlerraumabdeckung nach Sampling 5
Grundlagen 2.3 Die CPU Zyklen liegen auf der x- und die Speicherbits auf der y-Achse, da zu jedem zufälligen Zeitpunkt ein zufälliger Bit-Flip auftreten kann. Je vollständiger ein Fehlerin- jektionstool den Fehlerraum abdeckt, desto besser ist die Evaluation der Fehlertoleranz des Zielsystems. Um den Fehlerraum abzudecken müssen also mehrere Fehlerinjekti- on durchgeführt werden, d.h. das Zielsystem wird gestartet und nach einer gewissen Zeit wird ein Bit geflippt. Daraufhin wird das Ergebnis der spezifischen Fehlerinjektion gespeichert. Damit ist eine Fehlerinjektion abgeschlossen und ein Punkt aus dem Feh- lerraum abgedeckt. Danach folgt eine weitere Fehlerinjektion mit einem anderem Punkt aus dem Fehlerraum. Deckt ein Fehlerinjektionstool Schritt für Schritt einen Punkt aus dem Fehlerraum ab, sodass zum Schluss der komplette Fehlerraum abgedeckt ist, spricht man von einer vollständigen Fehlerraumabdeckung, siehe Abbildung 2.2. Die Alterna- tive dazu lautet Sampling. Hierbei werden eine beliebige Anzahl von Fehlerinjektionen gemacht, wobei jedes mal ein zufälliger Zeitpunkt und ein zufälliges Bit ausgewählt wird, siehe Abbildung 2.3. Dadurch wird zwar nicht der vollständige Fehlerraum abge- deckt, aber das Vorgehen ist deutlich schneller und bei einer ausreichenden Anzahl von Fehlerinjektionen können trotzdem aussagekräftige Ergebnisse über die Fehlertoleranz gemacht werden. Sampling ist demnach ein Kompromiss aus Fehlerraumabdeckung und Geschwindigkeit. 2.3.5 Ablauf von Fehlerinjektionstools Das typische Vorgehen von Fehlerinjektionstools ist zunächst einen Golden Run durch- zuführen. Das bedeutet, dass das Testsystem einmal ohne injizierten Fehler durchläuft, um das standardmäßige Verhalten zu testen und Daten für die folgenden Fehlerinjek- tion zu ermitteln. Es wird zum Beispiel die Ausgabe abgespeichert, damit diese mit den Ausgaben der Fehlerinjektionen verglichen werden können. Wenn sich eine Ausga- be gegenüber der vom Golden Run unterscheidet, konnte das System den injizierten Fehler nicht erkennen, bzw. beheben. Nach dem Golden Run werden die eigentlichen Fehlerinjektionen durchgeführt, dessen einzelne Ergebnisse alle gespeichert und ggf. au- tomatisiert evaluiert werden. 6
3 Literatur In diesem Kapitel wird Fail* [11] vorgestellt, das Fehlerinjektionstool welches als Refe- renz, für das in dieser Bachelorarbeit vorgestellte Fehlerinjektionstool, verwendet wird. Fail* ist ein umfangreiches Fehlerinjektion-Framework, welches sowohl software-implementierte, als auch simulationsbasierte Fehlerinjektion unterstützt. Es können unterschiedliche Si- mulatoren verwendet werden, wie zum Beispiel Bochs [12], Gem5 [13] oder OpenOCD [14], wobei die Verwendung mit Bochs am optimiertisten und am besten getestet ist. Fail* unterstützt sowohl Sampling, als auch die vollständige Fehlerraumabdeckung. Des weiteren enthält Fail* Optionen, die die Laufzeit der Tests deutlich verbessern, wie z.B. Multithreading und def/use Pruning. Mithilfe von def/use Pruning ist es mög- lich, den zu testenden Fehlerraum deutlich zu verkleinern. Man stellte fest, dass alle Fehlerstellen zwischen dem def (schreiben) oder use (lesen) von Speicherdaten äquiva- lent sind [15]. Das bedeutet man kann die Fehlerinjektion in diesem Intervall auf eins reduzieren, anstatt jeden Punkt im Intervall zu testen. Durch diesen verkleinerten Feh- lerraum verbessert sich ebenfalls die Laufzeit. Abschließend erstellt Fail* automatisiert eine csv-Datei in der die Ergebnisse gespei- chert werden. Unter anderem die aufgetretenen Fehler, Standardabweichungen und Kon- fidenzintervalle. 7
4 Konzept In diesem Kapitel wird zunächst die Intention zum erstellen des Fehlerinjektiontools erklärt. Daraufhin wird das Konzept vorgestellt. 4.1 Intention Wie bereits erwähnt, funktioniert Fail* am besten in der Kombination mit Bochs. Dessen Ausführungsgeschwindigkeit ist jedoch relativ langsam, da bei Bochs die Maschinenbe- fehle nicht direkt ausgeführt werden. Qemu hingegen übersetzt die Prozessorinstruktion des Gastprozessors in Instruktion für den Wirtprozessor dynamisch und erreicht damit eine gute Ausführungsgeschwindigkeit. Die Idee ist ein Fehlerinjektionstool mit dem GDB zu entwickeln, welches mithilfe von Qemu die Fehlertoleranz von Betriebssystemen bewertet und dieses anschließend mit Fail* in Kombination mit Bochs vergleicht. 4.2 Konzept Der Golden Run und die Fehlerinjektion werden von jeweiligen GDB Skripts durchge- führt. Hierdurch entsteht die Verbindung zum Zielsystem, dessen Ausführung, ggf. die Fehlerinjektion und abschließend, das Speichern der Ergebnisse. Weitere nützliche Lo- gik kann mithilfe des Python-Interpreters von GDB hinzugefügt werden. Das Tool soll automatisiert eine beliebige Anzahl von zufallsbasierten Fehlerinjektionen durchführen können und anschließend eine Evaluation der Ergebnisse erstellen. Des weiteren soll das Tool generisch, im Bezug auf die zu testenden Qemu Programme, sein. Um dies zu realisieren, müssen jedoch bestimmte Stellen im Testprogramm, wie zum Beispiel Start und Ende der Benchmark Funktion, sowie Anfang und Ende der Speicheradressen, mit Labels gekennzeichnet sein. Diese Labels sollen vorher in eine Konfigurationsdatei vom Anwender eingegeben werden. Das Einlesen dieser Datei, sowie die Ausführung der GDB Skripte und das erstellen der Ergebnisevaluation werden von übergeordneten Python- Skripts durchgeführt. 4.2.1 Ergebnistypen Im Folgenden werden die möglichen Ergebnistypen von einer Fehlerinjektion aufgezeigt. Läuft das Programm nach der Fehlerinjektion ohne Komplikation durch und es gibt, falls vorhanden, keine Unterschiede zwischen den Ausgaben, so wird der Durchlauf als OK bewertet, d.h. nichts ist passiert. Gibt es jedoch einen Unterschied, so wird der Durchlauf mit SDC als Fehler bewertet. SDC bedeutet Silent Data Corruption, ein Fehler 9
Konzept 4.2 ist aufgetreten und es wurde nichts dagegen unternommen. Zusätzlich zum SDC gibt es noch weitere Fehler. Stürzt das System nach der Fehlerinjektion ab oder gerät in eine Endlosschleife, wird der Durchlauf mit CRASH, bzw. TIMEOUT bewertet. In dem Fall, dass der injizierte Fehler erkannt wird, springt das Programm an eine bestimmte Stelle, welche mit einem Label versehen ist. Falls das Programm nun an diese Stelle springt, wird der Durchlauf mit DETECTED bewertet, da der injizierte Fehler gefunden werden konnte. Als letzte Möglichkeit gibt es bei einigen von den vorgegebenen Testprogrammen noch einen Spezialfall. In diesem wird während der Ausführung eine bestimmte Funktion aufgerufen, cyg_test_output(). Der erste Parameter dieser Funktion enthält eine Zahl, welche Aussagen über den Ergebnistypen macht. Ist die Zahl 0 kam es zur SDC, bei jedem anderen Wert wird der Durchlauf mit OK bewertet. 10
5 Implementierung In diesem Kapitel wird zunächst die verwendete Software-Architektur vorgestellt, wel- che die Konzepte aus dem vorherigem Kapitel realisieren soll. Daraufhin wird die Im- plementierung der einzelnen Bestandteile genauer betrachtet. Zusätzlich dazu werden aufgetretene Probleme behandelt und die daraus folgenden Softwareänderungen bespro- chen. 5.1 Software-Architektur In Abbildung 5.1 wird die entwickelte Software-Architektur dargestellt. Die blauen Käs- ten sind Python-Skripts, die roten GDB-Skripts und die grünen sind Ergebnisse im .txt oder .csv Format. Zunächst kann der Anwender in der Konfigurationsdatei Dateipfad, die Labels für Benchmark Start und Ende, Speicheradressen Anfang und Ende konfigurieren, sowie Anzahl der Golden Runs und Anzahl der Fehlerinjektion einstellen. Daraufhin wird das Hauptskript Generic FI gestartet. Von diesem Skript aus werden alle anderen Bestand- teile der Software-Architektur gestartet oder erstellt. Zu beginn werden die Konfigura- tionsdaten eingelesen und gespeichert. Mit diesen Daten können nun die Golden Runs durchgeführt werden. 5.2 Golden Runs Damit die Fehlerinjektionen durchgeführt und evaluiert werden können, werden vor- erst noch einige Daten benötigt. Falls vorhanden die standardmäßige Ausgabe des Pro- gramms, um mögliche Fehler nach einer Fehlerinjektion zu erkennen. Des weiteren muss die Laufzeit des Programms gemessen werden. Mit dessen Hilfe wird der zufällige Zeit- punkt ausgewählt, zu dem der Fehler injiziert werden soll. Aus diesen Gründen werden die Golden Runs gemacht. Wie in Abbildung 5.1 dargestellt gibt es jeweils für Zeitmessung und Ausgabe, eigene GDB-Skripts. Ursprünglich war nur ein einziges Golden Run Skript vorgesehen, jedoch muss in manchen Programmen auch der Parameter von cyg_test_output() kontrolliert werden. Diese Kontrolle verursacht nämlich eine kurzzeitige Unterbrechung des Pro- gramms, aus dem eine Verfälschungder Zeitmessung resultiert. Deshalb wird zuerst die Zeit mit dem Golden Run Time Skript gemessen und danach werden die Ausgaben und ggf. der Parameter mithilfe von dem Golden Run Output gespeichert. Weil die Laufzeit minimal variieren kann, muss sie mehrmals gemessen werden. Dies hat zur Folge, dass das Golden Run Time Skript mehrmals ausgeführt werden muss, um die Zeit häufiger zu messen. Die Anzahl wird in der Konfigurationsdatei festgelegt. 11
Implementierung 5.2 configures reads writes User Config Generic FI Results reads starts starts reads All Fault Injection Results Script Starter Golden Run Results starts writes starts Golden Run Time Results writes Single Fault Injection Fault writes Golden Run Golden Run Golden Run Scripthelper Fault Injection Injection Output Scripthelper Time Result GDB Qemu Abbildung 5.1: Software-Architektur (grün: Ergebnisdateien, blau: Python-Skript, rot: GDB-Skript) 12
5.2 Implementierung Zum Berechnen der Zufallszeit für die späteren Fehlerinjektionen wird der Median der Messungen in Golden Run Results abgespeichert. Beide Skripts lesen zu Beginn das Python Skript Golden Run Scripthelper ein. Dieses Skript beinhaltet zusätzliche Logik, welche nach dem Einlesen in GDB benutzt werden kann. Hierdurch werden die Funktionen des GDB Skripts deutlich erweitert. Zuerst wird die Konfigurationsdatei mithilfe vom Scripthelper gelesen, da die Informationen beim Starten des GDB Skripts nicht übergeben werden können. Daraufhin verbindet sich GDB mit dem vom Anwender angegebenen Zielsystem. Als nächstes werden Haltepunkte an die Start- und Endadresse der Benchmark-Funktion platziert. Hierdurch wird das Zielsystem, sobald es eine dieser beiden Adressen erreicht, gestoppt und das GDB Skript übernimmt wieder die Kontrolle bis es das Zielsystem ggf. weiterlaufen lässt. Um also zum Start der Benchmark-Funktion zu kommen, wird das Zielsystem mit dem GDB Befehl continue fortgesetzt bis sie den Haltepunkt erreicht. 5.2.1 Golden Run Time Bis zu diesem Punkt sind Golden Run Time und Output noch nahe zu identisch. Danach verändern sie sich jedoch. Zunächst wird der weitere Ablauf von Golden Run Time ge- nauer beschrieben. Das Zielsystem steht nun am Start der Benchmark-Funktion. Um die Zeit der Benchmark-Funktion zu messen wird mithilfe der Python Funktion time.time_- ns() die vergangene Zeit seit der Epoche in Nanosekunden zurückgegeben. Dieser Wert wird zwischengespeichert und das Zielsystem wird fortgesetzt bis es zum zweiten Hal- tepunkt, am Ende der Benchmark-Funktion, gelangt. Daraufhin wird im GDB-Skript wieder die Zeit abgespeichert. Die Differenz der beiden Zeiten ist die gemessene Lauf- zeit. Diese wird mithilfe von Python, der Datei Golden Run Time Results, hinzugefügt. Danach wird die Verbindung zum Zielsystem getrennt und GDB wird geschlossen, das GDB Skript ist zu Ende. Solange die gewünschte Anzahl an Golden Runs noch nicht erreicht ist, startet das Python Skript, Generic FI, weitere Golden Run Time Skripts. Nachfolgend wird der Median der Messdaten bestimmt und letztendlich in Golden Run Results gespeichert. 5.2.2 Golden Run Output Nachdem alle Golden Run Times durchgeführt wurden, wird abschließend einmal das Golden Run Output Skript ausgeführt. Hier wird beim Start des Zielsystems die Datei Golden Run Results mitangegeben, sodass automatisch die Ausgabe in diese geschrieben wird. Zusätzlich dazu werden mithilfe der Labels, Anfang und Ende der Speicheradres- sen abgespeichert. Die Differenz von Ende und Anfang ergibt die Speichergröße, welche ebenfalls in Golden Run Results geschrieben wird. Denn diese wird bei der Fehlerinjek- tion für die Bestimmung der zufälligen Stelle des Bit-Flips benötigt. Zusätzlich zu den zwei Haltepunkten wird ggf. noch cyg_test_output() als Halte- punkt hinzugefügt. Nun wird das Zielsystem bei der Benchmark-Funktion fortgesetzt bis es den nächsten Haltepunkt erreicht. Falls das System nun bei cyg_test_output() hält, muss der Parameter ausgelesen und abgespeichert werden. Daraufhin kann das Zielsystem fortgesetzt werden bis es ans Ende der Benchmark-Funktion gelangt oder 13
Implementierung 5.4 nochmal bei cyg_test_output(). Die Realisation von diesem Ablauf ist jedoch kompli- zierter als zunächst angenommen. Das Problem ist, dass GDB herausfinden muss bei welchem Haltepunkt er sich befindet und basierend darauf, entsprechend vorgehen muss. Der aktuelle Haltepunkt kann zwar auf dem Terminal ausgegeben werden, dies hilft jedoch dem Skript nicht weiter. Letztendlich wurde eine Lösung mithilfe des Python- Interpreters in GDB gefunden. Es ist möglich die Haltepunkte über Python anzulegen und diese als Variable abzuspeichern, welche nützliche Funktionen haben. Einer dieser Funktionen ist hit_count(). Diese gibt zurück, wie häufig der entsprechende Haltepunkt getroffen wurde. Hiermit ist es möglich den aktuellen Haltepunkt herauszufinden, indem man sich die Anzahl der Treffer zwischenspeichert. Wenn nun die Trefferanzahl eines Haltepunktes größer als die vorherig abgespeicherte ist, dann ist dieser der aktuelle Haltepunkt. Jetzt kann, je nachdem welcher Haltepunkt getroffen wird, entsprechend reagiert wer- den. Ist das System schlussendlich beim Ende angekommen, wird die Verbindung ge- schlossen und GDB wird beendet. Somit ist auch der Golden Run Output fertig. 5.3 Script Starter Nachdem die Golden Runs abgeschlossen sind, wird das Script Starter Skript ausgeführt, welches die Fehlerinjektionen startet. Dieses zusätzliche Skript existiert, weil das Tool ursprünglich multithreadingfähig sein sollte. Die Idee ist, dass beliebig viele Script Star- ter Skripts gestartet werden können die wiederum alle ihre eigenen Fehlerinjektionen starten. Hierbei gab es jedoch noch Fehler beim speichern der Ergebnisse und es kam vor das Threads einfach angehalten sind. Aufgrund fehlender Zeit konnte dieses Feature leider nicht fertiggestellt werden. 5.4 Fault Injection Der Ablauf der Fehlerinjektion ist recht simpel. Das Zielsystem wird beim Start der Benchmark-Funktion fortgesetzt. Nach einer zufälligen Zeit soll das System angehalten werden, dann muss das GDB Skirpt ein zufälliges Bit flippen und das System wieder fortsetzen. Diesen Ablaufplan mithilfe von GDB ist jedoch deutlich komplizierter. In diesem Abschnitt werden die einzelnen Anforderungen und dessen Realisierung im Detail betrachtet. Das Skript beginnt im Grunde genau wie die Golden Run Skripts. Eingangs wird das Fault Injection Scripthelper Python Skript geladen, welches den GDB um notwendige Funktionalitäten erweitert. Daraufhin wird die Konfigurationsdatei gelesen, die den Da- teipfad und die Labels für die Haltepunkte enthält. Anschließend wird das Zielsystem gestartet und die Haltepunkte werden gesetzt. Zusätzlich zu Benchmark Start, Bench- mark Ende und cyg_out_output Haltepunkt, wird ggf. noch der Detect hinzugefügt. Im Falle dass der Fehler erkannt wird, springt das System in diese Funktion. Daraus folgt, dass der Durchlauf mit DETECT bewertet wird. Auch diese Haltepunkte werden mit Python angelegt, so dass im Falle eines Treffers wieder differenziert werden kann um welchen Haltepunkt es sich handelt. 14
5.4 Implementierung 5.4.1 Zufällige Unterbrechungen erzeugen Damit zufällige Fehler injiziert werden können, muss das Zielsystem beim Start der Benchmark-Funktion fortgesetzt und nach einer zufälligen Zeit unterbrochen werden. Zum Bestimmen der Zufallszeit wird die Median Laufzeit aus Golden Run Result benö- tigt. Hiermit und mithilfe des Python Moduls random lässt sich eine Zufallszahl zwischen 0.0 und der Median Laufzeit zurückgeben. Als nächstes wird ein akkurater Timer be- nötigt, der möglichst genau die vorgegebene Zeit abwartet, um danach das Zielsystem zu unterbrechen. Diese beiden Anforderungen stellten sich als sehr kompliziert heraus, sowohl ein genauer Timer, viel mehr aber die Unterbrechung selbst. Zum Realisieren dieser gab es mehrere mögliche Ansätze. 5.4.1.1 Timer-Thread Der erste Ansatz bestand daraus einen seperaten Timer-Thread mit dem GDB-Python- Interpreter zu starten. Dieser schläft während das Zielsystem läuft, bis die Zeit abge- laufen ist, woraufhin der GDB-Befehl interrupt ausgeführt wird. Dieser Befehl bewirkt dasselbe wie die Tastenkombination Strg+C und unterbricht das Zielsystem. Hierbei trat jedoch das erste Problem auf. Aufgrund der geringen Laufzeit der Benchmarkfunk- tionen, meistens nur ein bis zwei Millisekunden, wurde die Unterbrechung häufig erst nach dem Ende der Benchmark-Funktion abgefeuert. Daraufhin war es logisch, dass ein genauerer Timer benötigt wird. Die vielversprechendste Lösung ist die Benutzung des Systemaufrufs nanosleep, die mithilfe eines C-Wrappers im Scripthelper benutzt werden kann. Jetzt können die Unterbrechungen möglichst genau abgefeuert werden, jedoch trat hierbei das zweite Problem auf. Unterbrechungen zu bestimmten Zeitpunkten werden komplett ignoriert. Mit dem Befehl interrupt war es nur möglich das System am An- fang, bzw. am Ende der Benchmark-Funktion zu unterbrechen. Liegt die Zeit beispiels- weise mittendrin, wird der Befehl einfach ignoriert und erst nach Ende der Benchmark Funktion ausgeführt. Da die Unterbrechung durch den Befehl interrupt nicht direkt durchgeführt wird, muss ein anderer Ansatz gewählt werden. 5.4.1.2 Separater Prozess Aufgrund des nicht gewünschten Ergebnisses, ist ein alternativer Ansatz zum Unterbre- chen erforderlich. Die Idee ist, einen separaten Prozess zu erstellen, welcher ein kurzes Skript startet, dass die gewünschte Zeit schläft und danach eine Unterbrechung durch das Unix-Signal kill -SIGINT $(pidof gdb) an den GDB-Prozess sendet. Das Skript be- nutzt ebenfalls den Systemaufruf nanosleep. Der geplante Ablauf ist wie folgt. Der separate Prozess wird aus dem GDB-Skript heraus gestartet. Daraufhin wird das Zielsystem fortgesetzt. Nachdem der separate Pro- zess fertig mit schlafen ist, wird das Unterbrechungssignal gesendet. Das erste Problem an diesem Ansatz ist, dass das Skript meistens zu spät startet, wodurch ebenfalls das Unterbrechungssignal verzögert wird. Das hat wiederum zur Folge, dass das Zielsystem bereits am Ende der Benchmark-Funktion angelangt ist, wenn das Signal eintrifft. Lei- der ist es nicht möglich das Zielsystem außerhalb vom GDB-Prozess zu starten, was 15
Implementierung 5.4 das Problem elegant beheben würde. Trotzdem ist es möglich das Zielsystem und den separaten Prozess möglichst zeitgleich zu starten. Und zwar mithilfe der Signale kill -SIGSTOP(pid) und kill -SIGCONT(pid). Der Ablauf ändert sich daraus wie folgt. Das Zielsystem wird aus dem GDB-Skript heraus fortgesetzt. Direkt danach wird der ent- sprechende Unterprozess von GDB, welcher das Zielsystem behandelt, mit dem Signal kill -SIGSTOP(pid) gestoppt. Danach wird der separate Prozess gestartet. Kurz bevor nanosleep aufgerufen wird, wird das Signal kill -SIGCONT(pid) gesendet, wodurch das Zielsystem wieder weiterläuft. Über diesen Umweg wird beides möglich Zeitnah gestartet und das Unterbrechungssignal kommt rechtzeitig. Das Ergebnis ist jedoch dasselbe wie beim Timer-Thread Ansatz. Auch hier wird das Programm im besten Fall nur am Anfang oder Ende unterbrochen. Wird das Signal dazwischen gesendet, läuft das Zielsystem ungestört bis zum nächsten Haltepunkt und wird erst dann verarbeitet. Aus dem Grund, dass keine nützlichen Ergebnisse mit diesem Ansatz erzielt wurden, ist dieser ebenfalls nicht zielführend. 5.4.1.3 Background Execution Der letzte Ansatz der vorgestellt wird benutzt eine bestimmte Einstellung in GDB wo- durch tatsächlich zufällige Unterbrechungen erzeugt werden können. GDB verhält sich normalerweise synchron zum Zielsystem. Während das Zielsystem läuft, demnach wer- den keine GDB Befehle ausgeführt. Erst wenn das Zielsystem anhält, wird das GDB Skript wieder fortgeführt. Wird das Zielsystem nun weiter fortgesetzt, dann stoppt das GDB Skript wieder, usw.. Mithilfe der Background Execution ist das Verhalten der beiden jedoch asynchron. Es können also GDB Befehle vom Skript ausgeführt werden während das Zielsystem läuft. Die Idee ist, das Zielsystem im asynchronen Modus mit dem Befehl continue& fort- zusetzen. Daraufhin schläft das GDB Skript wieder für die gewünschte Zeit und führt danach den Befehl interrupt aus. Dieser Background Execution Ansatz führt zum ge- wünschten Ergebnis und unterbricht das Zielsystem nach der gewünschten Zeit. Dieser Modus ist im GDB jedoch noch etwas fehlerbehaftet. Die Unterbrechung findet zum Beispiel nicht statt, wenn nach dem interrupt noch weitere Befehle im Skript stehen. In diesem Fall werden erst die anderen Befehle ausgeführt und dann wird das Skript beendet. So würde der Ansatz keinen Mehrwert bringen, da nach der Unterbrechung noch weitere Befehle ausgeführt werden müssen. Um diesen Bug zu umgehen muss ein zweiter Thread erstellt werden, welcher den interrupt sendet. Demzufolge wird eine End- losschleife mit einem langen sleep ausgeführt, um möglichst wenig Leistung in Anspruch zu nehmen. Hierdurch beendet sich GDB nicht automatisch, weil es immer auf das Ende vom zweiten Thread wartet. Mithilfe der Background Execution lässt sich das Zielsystem nun nach der gewünsch- ten zufälligen Zeit unterbrechen. 5.4.2 Zufälliger Bit-Flip Jetzt wo das Zielsystem nach zufälliger Zeit unterbrochen wurde, muss der Fehler inji- ziert werden indem ein zufälliges Bit geflippt wird. Hierzu wird zunächst die zufällige 16
5.4 Implementierung Speicheradresse zwischen dem Start und Ende des Speichers bestimmt. Danach wird der Wert dieser Adresse ausgelesen und zwischengespeichert. Ein zufälliges Bit wird geflippt und die Adresse bekommt den neuen Wert zugewiesen. Nun wo der Fehler injiziert ist kann das System weiter fortgesetzt werden. 5.4.3 Fälle nach der Fehlerinjektion Nachdem der Fehler injiziert wurde und das System wieder läuft, können unterschied- liche Fälle auftreten. Im Folgenden werden alle Möglichkeiten und deren Behandlung betrachtet. Die Fälle für die Ausgabe, Detect und cyg_test_output() werden ähnlich wie im Golden Run abgefangen. Mithilfe der Trefferanzahl wird festgestellt welcher Haltepunkt getroffen wurde und je nachdem wird das entsprechende Ergebnis in Single Fault Injec- tion Result geschrieben. Der einzige Unterschied ist, dass nun der asynchrone Modus genutzt wird und man ohne weiteres nicht weiß, wann das Programm angehalten wurde. In diesem Fall können die Events vom GDB-Python-Interpreter angewandt werden. Im speziellen das Event stop. Dieses wird getriggert wann immer das Zielsystem gestoppt wird, ob durch Haltepunkt, Unterbrechung oder Absturz. An dieses Event kann eine Python Funktion gehangen werden, die immer beim auftreten des Events ausgeführt wird. 5.4.3.1 Crash Durch den injizierten Fehler ist es möglich, dass das Zielsystem abstürzt. Dieser Fall muss ebenfalls erkannt und abgespeichert werden. Auch hier hilft wieder die Trefferanzahl aus. Ist das Zielsystem angehalten worden und keiner der Trefferanzahlen hat sich erhöht, dann wird davon ausgegangen, dass das System abgestürzt ist. Dieses Ergebnis wird daraufhin in Single Fault Injection Result geschrieben. 5.4.3.2 Timeout Die letzte Möglichkeit die eintreten kann ist, dass das Zielsystem nach der Fehlerin- jektion in eine Endlosschleife gerät. Dieser Fall ist, im Vergleich zu den anderen, nicht so leicht abzufangen. Hierfür muss ein zusätzliches Skript in einem separaten Prozess gestartet werden. In diesem Skript wird zunächst um ein vielfaches der Median Laufzeit geschlafen. Tritt einer der obigen Fälle auf wird der separate Prozess getötet, bevor er abgelaufen ist. Wurde das System nach dem sleep immer noch nicht angehalten, ist es in einer Endlosschleife gefangen. Daraufhin wird der GDB Prozess getötet und der Durch- lauf wird mit dem Ergebnis TIMEOUT in Single Fault Injection Result gespeichert. Ein Spezialfall muss jedoch noch beachtet werden. Da cyg_test_output() häufig mehrmals aufgerufen wird, muss der Timeout Prozess kurz für die Behandlung des Falls gestoppt werden. Hierdurch wird sicher gestellt, dass der Durchlauf nicht fälschli- cherweise als TIMEOUT gekennzeichnet wird. Das stoppen und fortsetzen des Timeout Prozesses kann wieder anhand von kill -SIGSTOP(pid) und kill -SIGCONT(pid) umge- setzt werden. 17
Implementierung 5.5 5.4.4 Abschluss der Fehlerinjektion Nachdem eine Fehlerinjektion abgeschlossen ist sind in Single Fault Injection Result alle Ergebnisse dieses Durchlaufes gespeichert. Diese bestehen aus der seriellen Ausgabe, der Zeitpunkt der Unterbrechung, die Adresse des Bit Flips, die Parameterwerte von cyg_- test_output(). Zusätzlich dazu werden ggf. noch die Fälle DETECTION, CRASH oder TIMEOUT hinzugefügt. Das Script Starter Skript überträgt nach Abschluss des Durch- laufs dessen Ergebnisse nach All Fault Injection Results. Hier werden alle Ergebnisse der Durchläufe mit Nummerierung gespeichert. Danach wird die nächste Fehlerinjektion gestartet, bis die gewünschte Anzahl erreicht ist. 5.5 Auswertung erstellen Nachdem die Fehlerinjektionen abgeschlossen sind, wird im Generic FI Skript die Er- gebnisdatei erstellt und die Werte für die Auswertung werden berechnet. Damit die Ergebnisse leichter zu verarbeiten sind, werden diese zunächst aus All Fault Injection Results gelesen und in eine Liste bestehend aus allen Durchläufen gespeichert. Zusätz- lich dazu werden Durchläufe die nicht mit OK bewertet wurden in eine weitere Liste gespeichert. Nachdem die Listen befüllt wurden können die Werte für die Auswertung berechnet werden. 5.5.1 Fehlerraumgröße Damit die folgenden Werte nicht durch den Samling-Ansatz verfälscht werden, müssen die Ergebnisse auf den Fehlerraum hochgerechnet werden [15]. Die Formel hierfür lautet: w = maximale Lauf zeit ∗ Speichergrösse Die maximale Laufzeit und die Speichergröße stehen bereits in Golden Run Result, also kann der Fehlerraum ohne Probleme berechnet werden. 5.5.2 Hochgerechnete Fehlerrate Mithilfe der hochgerechneten Fehlerrate können verschiedene Varianten eines Programms verglichen werden. Dieser Wert wird für jeden möglichen Ergebnistypen berechnet, also OK, SDC, TIMEOUT, DETECT und CRASH. Man kann zum Beispiel die hochgerech- nete SDC Fehlerrate von dem Programm mit implementierten Fehlertoleranzverfahren und dem unveränderten Programm vergleichen, um zu testen ob die Verfahren die Feh- lerrate verringern konnten. Zum berechnen wird folgende Formel angewandt [15]: Anzahl der F ehler Hochgerechnete F ehlerrate = ∗ F ehlerraum Anzahl der Injektionen 5.5.3 Konfidenzintervall Des weiteren werden die Konfidenzintervalle aller Ergebnistypen für die Konfidenznive- aus 95, 98 und 99 berechnet. 18
5.5 Implementierung Ergebnistyp Anzahl korrigierte Anzahl ... OK 49886 3238134469025184 ... SDC 34 2206963315296 ... TIMEOUT 62 4024462516128 ... CRASH 18 1168392343392 ... DETECT 0 0 ... Tabelle 5.1: Beispieltabelle mit den berechneten Werten N r. Ausgabe P arameter Beendet bei Zeitpunkt Stelle 1602 0 cyg_test_exit 0.002025827 0x114098 1887 Timeout 0.005104986 0x1147e9 3381 1 Crash 0.006884474 0x114613 ... ... ... ... ... ... Tabelle 5.2: Beispieltabelle zur Auflistung von Fehlerinjektionen 5.5.4 Relativer Standardfehler Der relative Standardfehler gibt an, wie gut das Konfidenzniveau ist. Es beschreibt, ob genügend Fehlerinjektionen gemacht worden sind. Je niedriger der Wert desto besser. Zum berechnen des relativen Standardfehlers wird der normale Standardfehler benötigt. Dieser wird mit folgender Formel berechnet [15]: s F ehlerrate(1 − F ehlerrate) Standardf ehler = Anzahl der Injektion Daraufhin kann der relative Standardfehler mit dieser Formel berechnet werden [15]: Standardf ehler relativer Standardf ehler = F ehlerrate 5.5.5 Resultierende Auswertungsdatei Die Auswertungsdatei wird im CSV Dateiformat abgespeichert. Tabellenkalkulations- programme können diese Dateien üblicherweise einlesen, sodass eine übersichtliche Ta- belle entsteht. Die ersten Zeilen der Tabelle beinhalten Informationen über den kompletten Test, wie zum Beispiel Anzahl der Injektion, Anzahl aller Fehler und die gesamte Laufzeit. Danach kommt eine Tabelle, die die berechneten Werte darstellt. Dessen Struktur kann in Tabelle 5.1 gesehen werden. Die Tabelle enthält noch weitere Spalten in denen die restlichen Werte aufgelistet sind. Anschließend werden alle aufgetretenen Fehler, wie in Tabelle 5.2, aufgelistet. Darun- ter wird abschließend das Ergebnis jedes einzelnen Durchlaufs repräsentiert. Damit ist sowohl die Auswertungsdatei, als auch die komplette Fehlerinjektion abgeschlossen. 19
6 Evaluation In diesem Kapitel wird das vorgestellte Fehlerinjektions-Tool evaluiert und die erzielten Ergebnisse werden mit denen von Fail* verglichen. 6.1 Gleichverteilung der Fehlerinjektionen Um die Plausibilität der Ergebnisse zu prüfen muss vorerst nachgewiesen werden, dass die Zeitpunkte der Fehlerinjektionen tatsächlich gleich verteilt ist. Wäre das nicht der Fall, dann würde der Fehlerraum nicht korrekt abgedeckt werden und die Ergebnisse wären nicht aussagekräftig. Um dies zu kontrollieren wird der Zeitpunkt und die Spei- cherstelle jeder einzelnen Fehlerinjektion benötigt. Diese Information stehen sowohl in der Auswertungsdatei, als auch in All Fault Injection Results. Mit diesen Daten kann ein zwei-dimensionales Diagramm erstellt werden, welches den Fehlerraum mit den ein- zelnen Fehlerinjektionen widerspiegelt. Das Diagramm kann mithilfe eines einfachen Python-Skripts und dem Modul matplotlib erstellt werden. In Abbildung 6.1 ist ein solches Diagramm zu sehen. Die Daten stammen von dem Testprogramm sync3, in dem das Fehlertoleranzverfahren gop2_crc implementiert wur- de. Bei diesem Test wurden 50000 Durchläufe gemacht und die Median Laufzeit der Benchmark-Funktion betrug 0,0017978 Sekunden. Dem Diagramm ist zu entnehmen, dass die Fehlerinjektionen bis kurz vor 0,002 Sekunden gleich verteilt sind. Trotzdem gibt es einige Unterbrechungen die erst deutlich nach der Median Laufzeit eintraten und dementsprechend nutzlos sind. Der Grund für die Verzögerten Fehlerinjektionen ist vermutlich der Scheduler, wodurch die Timer aufgeschoben werden. Die Folge von den verzögerten Fehlerinjektionen ist, dass die Evaluation der Fehler- toleranz ungenauer wird, da einige Durchläufe überhaupt keinen Fehler injiziert haben. Trotzdem können die Evaluationen noch aussagekräftig sein, weil Verbesserungen durch Fehlertoleranzmechanismen immer noch festgestellt werden können, dies jedoch etwas ungenauer. Um diese ungenauigkeit zu vermeiden kann man nur die Fehlerinjektionen betrachten, welche innerhalb der Median-Laufzeit sind. Dementsprechend müsste dann auch die Anzahl der Durchläufe verändert werden. So werden nur die wirklich aussagekräftigen Fehlerinjektionen berücksichtigt. 6.2 Evaluierung der Tests In diesem Abschnitt wurden mithilfe des Fehlerinjektion-Tools Programme getestet, um deren Fehlertoleranz zu prüfen und mögliche Verbesserung durch Fehlertoleranzver- 21
Evaluation 6.2 1165000 1160000 1155000 Speicherbereich 1150000 1145000 1140000 0.000 0.002 0.004 0.006 0.008 0.010 Zeit Abbildung 6.1: Fehlerraumdiagramm mit 50000 Fehlerinjektionen fahren festzustellen. Dieselben Programme wurden auch mit Fail* getestet, sodass die Ergebnisse miteinander verglichen werden können. In Tabelle 6.1 sind die Ergebnisse von einem Test mit dem Programm sync3 mit der baseline Variante zu sehen. Baseline bedeutet, dass hier keine zusätzlichen Feh- lertoleranzmechanismen implementiert sind. Deswegen fehlt in der Tabelle auch der Ergebnistyp DETECT. Anhand der Fehlerraten lassen sich nun die unterschiedlichen Varianten des gleichen Programms vergleichen. In Tabelle 6.2 wurde die Variante gop2_crc getestet. Bei beiden Tests wurden jeweils 50000 Fehlerinjektionen durchgeführt. Man kann erkennen, dass die Fehlerraten bei der gop2_crc Variante gesunken sind. Durch die implementierten Fehlertoleranzverfahren konnte die Fehlertoleranz also verbessert werden. In Tabelle 6.3 und Tabelle 6.4 wurden dieselben Programme mit Fail* in Kombination mit Bochs im Sampling-Verfahren getestet. Auch hier wurden beide Tests mit 50000 Fehlerinjektion ausgeführt. Des weiteren wurde das def/use Pruning verwendet, um den Fehlerraum zu verkleinern und die Laufzeit zu verbessern. Auch hier erkennt man, dass die Anzahl der Durchläufe, welche mit OK bewertet wurden, sich deutlich durch die gop2_crc Variante verbessert haben. Die Konfidenzniveaus der beiden Tools lassen sich durch den relativen Standardfeh- ler vergleichen. Diese liegt bei dem GDB Fehlerinjektions Tool für den Ergebnistyp OK bei 17,1499%. Dieser ist vergleichsweise hoch und bedeutet, dass eigentlich mehr Durchläufe gemacht werden müssen. Fail* hingegen liegt hier bei 1,344%. Bei gleicher Fehlerinjektionsanzahl liefert Fail* ein deutlich besseres Konfidenzniveau. Das ist ein 22
6.3 Evaluation Ergebnistyp F ehlerrate korrigierte F ehlerrate relativer Standardf ehler OK 0.99772 64.762.689.380,503685 0,004477242924567388 SDC 0.00068 44.139.266,305920005 0,17149858514250882 TIMEOUT 0.00124 80.489.250,32256 0,1270001270001905 CRASH 0.00036 23.367.846,867840003 0,23570226039551584 Tabelle 6.1: Auswertung von sync3_baseline nach 50000 Fehlerinjektionen Ergebnistyp F ehlerrate korrigierte F ehlerrate relativer Standardf ehler OK 0.99956 51.667.774.284,030716 0,004473120149705844 SDC 0.0001 5.169.051,811199999 0,4472135954999579 TIMEOUT 0.00018 9.304.293,26016 0,3333333333333333 CRASH 0.00016 8.270.482,897919999 0,35355339059327373 DETECT 0.00446 230539710,77951998 0,0669649530182425 Tabelle 6.2: Auswertung von sync3_gop2_crc nach 50000 Fehlerinjektionen Ergebnistyp korrigierte Anzahl relativer Standardf ehler OK 49.096.159,6736 0,003268102 SDC 7.507.371,2896 0,013440315 TIMEOUT 4.475.200,6624 0,017792892 CRASH 8.270.482,897919999 0,00926331 Tabelle 6.3: Auswertung von sync3_baseline mit Fail* nach 50000 Fehlerinjektionen Ergebnistyp korrigierte Anzahl relativer Standardf ehler OK 57.931.189,3030 0,004534646 SDC 6.558.469,5309 0,018392784 TIMEOUT 3.200.514,3322 0,02672479 CRASH 16.526.591,2614 0,011053815 DETECT 33.276.419,5725 0,023917908 Tabelle 6.4: Auswertung von sync3_gop2_crc mit Fail* nach 50000 Fehlerinjektionen plausibles Ergebnis, weil Fail* def/use Pruning benutzt und das GDB Tool nicht. Um diese Diskrepanz auszugleichen müssten also mehr Fehlerinjektionen machen. Zum Abschluss wird die Laufzeit des Tools betrachtet. Leider stehen keine Informa- tionen zur Laufzeit von Fail* zur Verfügung, wodurch dieser wichtige Vergleich entfällt. Trotzdem gibt es interessante Punkte zu der Laufzeit des GDB Tools. Die gesamte Laufzeit für den 50000er Test mit der baseline Variante betrug 3 Stunden und 10 Mi- nuten. Vergleicht man das mit der hochgerechneten Median-Laufzeit von 5 Minuten, also Median-Laufzeit * 50000, sieht man, dass sich die Laufzeit durch den Testcode um 3 Stunden und 5 Minuten verlängert. Viel Zeit in Anspruch nimmt das Speichern je- des einzelnen Durchlaufs, und daraufhin das neu starten von GDB und Qemu. Hinzu kommt das die Fehlerinjektionen selbst die Laufzeit erhöhen, weil das Zielsystem kurz angehalten werden muss oder im schlechtesten Fall sogar in eine Endlosschleife gerät. 23
Evaluation 6.3 6.3 Verbesserungsmöglichkeiten Das Tool liefert zwar aussagekräftige Ergebnisse, jedoch sind diese deutlich ungenauer als die von Fail*. Damit das Tool genauere Ergebnisse erzielt müssten mehr Fehler- injektionen gemacht werden. Hierdurch würde jedoch auch wieder die Laufzeit erhöht werden, wobei diese eigentlich der Vorteil von dem Tool sein sollte. Mithilfe von Multithreading wäre es möglich mehr Injektionen durchzuführen, bzw. die Laufzeit noch weiter zu senken. Mit der Implementation wurde schon begonnen, jedoch konnte diese aufgrund von Zeitproblemen nicht fertiggestellt werden. Es war bereits möglich mehrere Threads zu erstellen, welche alle ihre eigenen Fehlerinjektionen durchführten. Es gab jedoch noch Komplikationen mit der Speicherung der Ergebnisse und seltenen Abstürzen. Wird dieses Feature in Zukunft noch fertiggestellt, dann kann die Genauigkeit, sowie die Laufzeit deutlich verbessert werden. Die zweite Verbesserungsmöglichkeit wäre, sowohl die Laufzeit, als auch die Genau- igkeit mithilfe vom def/use Pruning zu verbessern. Dieses Feature ist ebenfalls in Fail*, jedoch noch nicht im GDB-Tool enthalten. 24
7 Zusammenfassung Im Rahmen dieser Bachelorarbeit wurde ein GNU Debugger Fehlerinjektions-Tool ent- wickelt, zum automatisiertem evaluieren der Fehlertoleranz. Zunächst gab es einen Über- blick über die Grundlagen und Literatur die zum entwickeln des Tools benötigt wurden. Daraufhin wurde das Konzept vorgestellt und anschließend dessen Implementation be- schrieben. Abschließend wurde das Tool mit Fail* verglichen und evaluiert. Die größte Herausforderung war es, die zufälligen Unterbrechungen zu erzeugen. Hier wurden viele verschiedene Ansätze getestet, welche alle nicht erfolgreich waren, bis schlussendlich mithilfe der Background-Execution von GDB die gewünschten Ergebnisse erzielt werden konnten. Aber auch für diesen Ansatz mussten Bugs und Fehler umgan- gen werden. Des weiteren stellte sich der Python-Interpreter von GDB als große Hilfe heraus. Hiermit konnte dem GDB Skript erst die nötige Logik bereitgestellt werden ohne die es sonst nicht möglich, bzw. deutlich komplizierter wäre, die Software-Architektur und die Fehlerinjektion zu realisieren. Die abschließende Evaluation und der Vergleich mit Fail* hat gezeigt, dass das Tool aussagekräftige Ergebnisse liefert mit dem die Fehlertoleranz evaluiert werden kann. Jedoch stellte sich auch heraus, dass das Konfidenzniveau im Vergleich zu Fail* deutlich schlechter ist und eigentlich mehr Injektionen durchgeführt werden müssen. Das Tool hat noch Potential übrig, weil sich durch die bereits noch nicht implemen- tierten Features, Multithreading und def/use Pruning, die Genauigkeit und Laufzeit noch verbessern kann. 25
Literaturverzeichnis [1] International Roadmap Committee. International technology roadmap for semi- conductors, 2013 edn. (executive summary). Semiconductor Industry Association, 2013. [2] Vijaykrishnan Narayanan and Yuan Xie. Reliability concerns in embedded system designs. Computer, 39(1):118–120, 2006. [3] Robert Baumann. Soft errors in advanced computer systems. IEEE Design & Test of Computers, 22(3):258–266, 2005. [4] Edmund B Nightingale, John R Douceur, and Vince Orgovan. Cycles, cells and platters: an empirical analysisof hardware failures on a million consumer pcs. In Proceedings of the sixth conference on Computer systems, pages 343–356, 2011. [5] Andy A Hwang, Ioan A Stefanovici, and Bianca Schroeder. Cosmic rays don’t strike twice: Understanding the nature of dram errors and the implications for system design. ACM SIGPLAN Notices, 47(4):111–122, 2012. [6] Elena Dubrova. Fault-tolerant design. Springer, 2013. [7] Peter Alan Lee and Thomas Anderson. Fault tolerance. In Fault Tolerance, pages 51–77. Springer, 1990. [8] Christoph Borchert, Horst Schirmeier, and Olaf Spinczyk. Generic soft-error de- tection and correction for concurrent data structures. IEEE Transactions on De- pendable and Secure Computing, 14(1):22–36, 2015. [9] Johan Karlsson, Peter Liden, Peter Dahlgren, Rolf Johansson, and Ulf Gunneflo. Using heavy-ion radiation to validate fault-handling mechanisms. IEEE micro, 14(1):8–23, 1994. [10] Haissam Ziade, Rafic A Ayoubi, Raoul Velazco, et al. A survey on fault injection techniques. Int. Arab J. Inf. Technol., 1(2):171–186, 2004. [11] Horst Schirmeier, Martin Hoffmann, Christian Dietrich, Michael Lenz, Daniel Loh- mann, and Olaf Spinczyk. Fail*: An open and versatile fault-injection framework for the assessment of software-implemented hardware fault tolerance. In 2015 11th European Dependable Computing Conference (EDCC). IEEE, 2015. [12] Kevin P Lawton. Bochs: A portable pc emulator for unix/x. Linux Journal, 1996(29es):7–es, 1996. 27
Literaturverzeichnis .0 [13] Nathan Binkert, Bradford Beckmann, Gabriel Black, Steven K Reinhardt, Ali Sai- di, Arkaprava Basu, Joel Hestness, Derek R Hower, Tushar Krishna, Somayeh Sar- dashti, et al. The gem5 simulator. ACM SIGARCH computer architecture news, 39(2):1–7, 2011. [14] Hubert Högl and Dominic Rath. Open on-chip debugger–openocd–. Fakultat fur Informatik, Tech. Rep, 2006. [15] Horst Schirmeier, Christoph Borchert, and Olaf Spinczyk. Avoiding pitfalls in fault- injection based comparison of program susceptibility to soft errors. In 2015 45th An- nual IEEE/IFIP International Conference on Dependable Systems and Networks, pages 319–330. IEEE, 2015. 28
Abbildungsverzeichnis 2.1 Fehlerraum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.2 vollständige Fehlerraumabdeckung . . . . . . . . . . . . . . . . . . . . . 5 2.3 Fehlerraumabdeckung nach Sampling . . . . . . . . . . . . . . . . . . . . 5 5.1 Software-Architektur (grün: Ergebnisdateien, blau: Python-Skript, rot: GDB-Skript) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 6.1 Fehlerraumdiagramm mit 50000 Fehlerinjektionen . . . . . . . . . . . . 22 29
Tabellenverzeichnis 5.1 Beispieltabelle mit den berechneten Werten . . . . . . . . . . . . . . . . 19 5.2 Beispieltabelle zur Auflistung von Fehlerinjektionen . . . . . . . . . . . . 19 6.1 Auswertung von sync3_baseline nach 50000 Fehlerinjektionen . . . . . . 23 6.2 Auswertung von sync3_gop2_crc nach 50000 Fehlerinjektionen . . . . . 23 6.3 Auswertung von sync3_baseline mit Fail* nach 50000 Fehlerinjektionen 23 6.4 Auswertung von sync3_gop2_crc mit Fail* nach 50000 Fehlerinjektionen 23 31
Erklärung zur selbstständigen Abfassung der Bachelorarbeit Ich versichere, dass ich die eingereichte Bachelorarbeit selbstständig und ohne unerlaubte Hilfe verfasst habe. Anderer als der von mir angegebenen Hilfsmittel und Schriften habe ich mich nicht bedient. Alle wörtlich oder sinngemäß den Schriften anderer Autoren entnommenen Stellen habe ich kenntlich gemacht. Ort, Datum, Unterschrift 33
Sie können auch lesen