Bachelorarbeit Automatisierte Fehlerinjektion mit dem GNU Debugger

Die Seite wird erstellt Felix-Stefan Sonntag
 
WEITER LESEN
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