diff options
| author | Manuel Traut <manut@linutronix.de> | 2012-03-14 06:20:14 +0100 |
|---|---|---|
| committer | Manuel Traut <manut@linutronix.de> | 2018-03-16 21:36:58 +0100 |
| commit | ce5c7229abcc66a7cb03d031bafc96c4568aa9bd (patch) | |
| tree | 984d071d332b947a8e30f1453dd2901ca8a1fced | |
| parent | a0ab1993cf56e18142c81d6cfc0fd5082b0ac3ce (diff) | |
fix ae oe ue in tex files
Signed-off-by: Manuel Traut <manut@linutronix.de>
| -rw-r--r-- | application-devel/app-debugging/handout_app-debugging_de.tex | 86 | ||||
| -rw-r--r-- | application-devel/devel-environment/handout_devel-environment_de.tex | 2 | ||||
| -rw-r--r-- | flash-memory/mtd/handout_mtd_de.tex | 80 | ||||
| -rw-r--r-- | flash-memory/ubi/handout_ubi_de.tex | 96 | ||||
| -rw-r--r-- | kernel-devel/uio-driver/handout_uio-driver_de.tex | 510 | ||||
| -rw-r--r-- | linux-basics/boot-process/handout_boot-process_de.tex | 122 | ||||
| -rw-r--r-- | linux-basics/what-is-linux/handout_what-is-linux_de.tex | 142 | ||||
| -rw-r--r-- | realtime/rt-basics/handout_rt-basics_de.tex | 116 | ||||
| -rw-r--r-- | realtime/rt-specialties/handout_rt-specialties_de.tex | 116 |
9 files changed, 635 insertions, 635 deletions
diff --git a/application-devel/app-debugging/handout_app-debugging_de.tex b/application-devel/app-debugging/handout_app-debugging_de.tex index b082790..a51177a 100644 --- a/application-devel/app-debugging/handout_app-debugging_de.tex +++ b/application-devel/app-debugging/handout_app-debugging_de.tex @@ -3,7 +3,7 @@ \subsection{Applikationen Debuggen} \subsubsection{STRACE} -Eine sehr einfache und mächtige Möglichkeit, Systemaufrufe und Signale +Eine sehr einfache und m\"achtige M\"oglichkeit, Systemaufrufe und Signale zu tracen, ist das Tool ''strace''. Die Anwendung ist denkbar einfach. Dem Aufruf des zu tracenden Programms wird einfach strace vorangestellt: \begin{lstlisting}[language=bash] @@ -41,9 +41,9 @@ davon sind:\\ \subsubsection{GDB} \paragraph{Interaktives Debugging mit GDB} Der GNU Debugger: GDB stellt einen vollwertigen interaktiven Debugger dar, -der für alle gängigen Prozessorarchitekturen verfügbar ist. GDB bietet ein -sehr mächtiges Commandlineinterface. Es existieren diverse grafische Frontends -für GDB (z.B. DDD). Eine einfache Debuggingsession stellt sich wie folgt dar: +der f\"ur alle g\"angigen Prozessorarchitekturen verf\"ugbar ist. GDB bietet ein +sehr m\"achtiges Commandlineinterface. Es existieren diverse grafische Frontends +f\"ur GDB (z.B. DDD). Eine einfache Debuggingsession stellt sich wie folgt dar: \begin{lstlisting}[language=c] /* hello.c */ #include <stdio.h> @@ -54,7 +54,7 @@ für GDB (z.B. DDD). Eine einfache Debuggingsession stellt sich wie folgt dar: return 0; } \end{lstlisting} -Übersetzen des Programms mit Debuginformationen: +\"Ubersetzen des Programms mit Debuginformationen: \begin{lstlisting} $ gcc -g -o hello hello.c \end{lstlisting} @@ -67,7 +67,7 @@ Hello world Program exited normally. \end{lstlisting} -Mit dem Kommando ''list'' kann der zugehörige Quellcode angezeigt werden. +Mit dem Kommando ''list'' kann der zugeh\"orige Quellcode angezeigt werden. Breakpoints werden mit ''break'' gesetzt: \begin{lstlisting} (gdb) list @@ -81,8 +81,8 @@ Breakpoints werden mit ''break'' gesetzt: (gdb) break 5 Breakpoint 1 at 0x400528: file hello.c, line 5. \end{lstlisting} -Mit ''next'' und ''step'' werden einzelne Codezeilen ausgeführt, -während ''next'' einem step-OVER und ''step'' einem step-IN entspricht: +Mit ''next'' und ''step'' werden einzelne Codezeilen ausgef\"uhrt, +w\"ahrend ''next'' einem step-OVER und ''step'' einem step-IN entspricht: \begin{lstlisting} (gdb) run Starting program: /home/jan/work/examples/hello @@ -95,11 +95,11 @@ Hello world (gdb) continue Continuing. \end{lstlisting} -Folgende Tabelle zeigt eine Übersicht der wichtigsten GDB Kommandos:\\ +Folgende Tabelle zeigt eine \"Ubersicht der wichtigsten GDB Kommandos:\\ \begin{center} \begin{tabular}{|l|c|p{8cm}|} \hline -\textbf{Kommando} & \textbf{Abkürzung} & \textbf{Zweck} \\ +\textbf{Kommando} & \textbf{Abk\"urzung} & \textbf{Zweck} \\ \hline run & r & Programm starten \\ \hline @@ -125,7 +125,7 @@ quit & q & GDB beenden \\ \end{center} \paragraph{Analyse von core-Files} -Neben der Möglichkeit des interaktiven Debuggings findet GDB auch häufig +Neben der M\"oglichkeit des interaktiven Debuggings findet GDB auch h\"aufig eine weitere Anwendung: Die ''Post-Mortem-Analyse'' von Problemen. Wird eine Applikation beispielsweise durch seinen Segmentation Fault beendet, wird ein sogenanntes core-File erzeugt, welches u.A. den aktuellen Stack der @@ -134,11 +134,11 @@ und kann mit dem Kommanto ''ulimit'' aktiviert werden: \begin{lstlisting} ulimit -c unlimited \end{lstlisting} -Die maximale Größe des zu erzeugenden core-Files wird ulimit als Parameter -übergeben. Gibt es keine Größenbeschränkung kann einfach ''unlimited'' als -Parameter übergeben werden. Der Name des zu erzeugenden Files kann unter +Die maximale Gr\"oße des zu erzeugenden core-Files wird ulimit als Parameter +\"ubergeben. Gibt es keine Gr\"oßenbeschr\"ankung kann einfach ''unlimited'' als +Parameter \"ubergeben werden. Der Name des zu erzeugenden Files kann unter /proc/sys/kernel/core\_pattern festgelegt werden. Folgende Formatoptionen -können hier verwendet werden: +k\"onnen hier verwendet werden: \begin{center} \begin{tabular}{|c|l|} \hline @@ -172,7 +172,7 @@ Folgendes Beispiel verdeutlicht die Analyse eines core-Files: return 0; } \end{lstlisting} -Programm übersetzen: +Programm \"ubersetzen: \begin{lstlisting} $ gcc -g -o segfault segfault.c \end{lstlisting} @@ -203,18 +203,18 @@ Program terminated with signal 11, Segmentation fault. \end{lstlisting} \subsubsection{Memory debugging} -Eine sehr häufige Problemstellung bei der Fehlersuche in Applikationen -ist das Aufspüren von Problemen in der dynamischen Speicherverwaltung. -Die häufigsten Probleme, die es hier zu untersuchen gilt, sind: +Eine sehr h\"aufige Problemstellung bei der Fehlersuche in Applikationen +ist das Aufsp\"uren von Problemen in der dynamischen Speicherverwaltung. +Die h\"aufigsten Probleme, die es hier zu untersuchen gilt, sind: \begin{itemize} -\item Schreiben / Lesen über die Grenze von Speicherbereichen +\item Schreiben / Lesen \"uber die Grenze von Speicherbereichen \item Memory leaks \item ''Use after free()'' \end{itemize} \paragraph{GLIBC: MTrace} Die GNU C Library, GLIBC, liefert bereits ein integriertes Werkzeug zum Debuggen von Speicherproblemen:MTrace. Die Anwendung von MTrace ist denkbar einfach. -Im ersten Schritt ist der Code um folgende Zeilen zu ergänzen: +Im ersten Schritt ist der Code um folgende Zeilen zu erg\"anzen: \begin{lstlisting} [...] #include <mcheck.h> @@ -243,7 +243,7 @@ int main(void) free(blurb); } \end{lstlisting} -Übersetzen und Ausführen der Applikation: +\"Ubersetzen und Ausf\"uhren der Applikation: \begin{lstlisting}[language=bash] $ gcc -g -o mem_leak mem_leak.c $ MALLOC_TRACE=mytrace.log ./mem_leak @@ -260,12 +260,12 @@ Address Size Caller 0x15364a0 0x1 at /home/jan/work/examples/mem_leak.c:13 [...] \end{lstlisting} -\paragraph{GLIBC: Hooks für malloc()} -Neben mtrace() sieht die GLIBC noch Hooks vor, um Callbacks einzuhängen, +\paragraph{GLIBC: Hooks f\"ur malloc()} +Neben mtrace() sieht die GLIBC noch Hooks vor, um Callbacks einzuh\"angen, die bei jedem Aufruf von malloc(), realloc(), free() oder memalign() -aufgerufen werden. Hiermit steht eine sehr einfache Möglichkeit zur Verfügung, -dynamische Speicherverwaltung individuell zu überwachen.\\ -Folgende Variablen sind für diesen Zweck vorgesehen:\\ +aufgerufen werden. Hiermit steht eine sehr einfache M\"oglichkeit zur Verf\"ugung, +dynamische Speicherverwaltung individuell zu \"uberwachen.\\ +Folgende Variablen sind f\"ur diesen Zweck vorgesehen:\\ \_\_malloc\_hook: \begin{lstlisting}[language=C] /* function prototype */ @@ -287,19 +287,19 @@ void *function (void *ptr, const void *caller) void *function (size_t size, size_t alignment, const void *caller) \end{lstlisting} ACHTUNG: Bei der Verwendung von malloc() Hooks ist Vorsicht geboten! Jeglicher -Aufruf, der seinerseits wiederrum einen malloc() Aufruf initiiert, führt +Aufruf, der seinerseits wiederrum einen malloc() Aufruf initiiert, f\"uhrt innerhalb eines malloc() Hooks unvermeidlich zu einer Rekursion. \paragraph{libDUMA} Ein weiteres bekanntes Werkzeug zum Speicherdebugging ist eine Bibliothek mit dem Namen DUMA. Hierbei handelt sich um einen Fork der bekannten -Electric Fence Libraries von Bruce Perence. DUMA ermöglicht es durch einfaches -Linken gegen die Bibliothek, Speicherprobleme wie Leaks oder das Schreiben über +Electric Fence Libraries von Bruce Perence. DUMA erm\"oglicht es durch einfaches +Linken gegen die Bibliothek, Speicherprobleme wie Leaks oder das Schreiben \"uber Array Grenzen hinaus zu detektieren. Hierzu bringt DUMA eigene Implementierungen -von malloc() und free(). Zum Detektieren von Überschriebenen Array Grenzen +von malloc() und free(). Zum Detektieren von \"Uberschriebenen Array Grenzen reicht das dynamische Linken oder das einfache ''Pre-loading'' gegen / von libDUMA. Erkennt DUMA einen Fehler wird ein Segmentation Fault erzeugt. Die Fehlersituation kann dann mittels core-File oder interaktivem Debuggen analysiert werden. Zum -Aufspüren von Memory Leaks muß statisch gegen libDUMA gelinkt und weiterhin +Aufsp\"uren von Memory Leaks muß statisch gegen libDUMA gelinkt und weiterhin duma.h inkludiert werden. Bezogen auf unser Beispiel bedeutet dies: \begin{lstlisting} /* mem_leak.c */ @@ -318,12 +318,12 @@ int main(void) free(blurb); } \end{lstlisting} -Übersetzen der Applikation (Achtung: Linkreihenfolge beachten!!!): +\"Ubersetzen der Applikation (Achtung: Linkreihenfolge beachten!!!): \begin{lstlisting}[language=bash,basicstyle=\ttfamily\fontsize{9}{9}\selectfont] $ gcc -g -o mem_leak mem_leak.c /usr/lib/libduma.a \ -lpthread \end{lstlisting} -Ausführen der Applikation: +Ausf\"uhren der Applikation: \begin{lstlisting} $ ./mem_leak DUMA 2.5.15 (static library) @@ -339,7 +339,7 @@ DUMA: ptr=0x7f7280bddfff size=1 type='malloc()' alloced from mem_leak.c(11) not freed [...] \end{lstlisting} -Das Detektieren von überschriebenem Speicher erfordert, wie bereits beschrieben, +Das Detektieren von \"uberschriebenem Speicher erfordert, wie bereits beschrieben, kein statisches Linken gegen libDUMA: \begin{lstlisting}[language=C] /* array_access.c */ @@ -399,20 +399,20 @@ DUMA\_PROTECT\_BELOW & DUMA platziert normalerweise ''Marker'' hinter dem allozi Das Setzen dieser Variable veranlaßt DUMA die Marker VOR den allozierten Bereich zu setzen\\ \hline DUMA\_REPORT\_ALL\_LEAKS & Alle Memory leaks anzeigen (auch wenn Sourcefile und Zeilennummer -nicht verfügbar sind)\\ +nicht verf\"ugbar sind)\\ \hline -DUMA\_ALLOW\_MALLOC\_0 & malloc() mit der Größe 0 als Fehler ausgeben\\ +DUMA\_ALLOW\_MALLOC\_0 & malloc() mit der Gr\"oße 0 als Fehler ausgeben\\ \hline \end{tabular} \end{center} Es gibt noch viele andere Environment Variablen. Deren Bedeutung ist der Manpage von libduma zu entnehmen: ''man duma'' \paragraph{Valgrind} -Valgrind ist das wohl mächtigste Werkzeug, das zur Analyse von Speicherproblemen -zur Verfügung steht. Es handelt sich um mehrere Werkzeuge, die unter anderem auch -Profiling Funkionaliät bieten. Valgrind erreicht eine sehr hohe Trefferquote. Leider -gibt es derzeit nur beschränkten Support für ARM CPUs (derzeit gibt es noch -harte Abhängigkeiten nach ARMv7). Die Analyse des Memory Leak Beispiels mit valgrind gestaltet +Valgrind ist das wohl m\"achtigste Werkzeug, das zur Analyse von Speicherproblemen +zur Verf\"ugung steht. Es handelt sich um mehrere Werkzeuge, die unter anderem auch +Profiling Funkionali\"at bieten. Valgrind erreicht eine sehr hohe Trefferquote. Leider +gibt es derzeit nur beschr\"ankten Support f\"ur ARM CPUs (derzeit gibt es noch +harte Abh\"angigkeiten nach ARMv7). Die Analyse des Memory Leak Beispiels mit valgrind gestaltet sich wie folgt: \begin{lstlisting}[language=C] /* mem_leak.c */ @@ -431,7 +431,7 @@ int main(void) free(blurb); } \end{lstlisting} -Übersetzen der Applikation: +\"Ubersetzen der Applikation: \begin{lstlisting}[language=bash] $ gcc -g -o mem_leak mem_leak.c \end{lstlisting} diff --git a/application-devel/devel-environment/handout_devel-environment_de.tex b/application-devel/devel-environment/handout_devel-environment_de.tex index 1ac1b6f..d36527c 100644 --- a/application-devel/devel-environment/handout_devel-environment_de.tex +++ b/application-devel/devel-environment/handout_devel-environment_de.tex @@ -38,7 +38,7 @@ H\"aufig eingesetzte textbasierte Editoren unter Linux sind: \item yed \end{itemize} -Hilfreich beim Arbeiten auf der Textkonsole ist auch das Programm \cmd{screen}. +Hilfreich beim Arbeiten auf der Textkonsole ist auch das Programm screen. Screen bietet eine Tab Funktionalit\"at f\"ur die Konsole. Z.b. kann in einem screen der Editor gestartet werden, in einem weitern make und im N\"achsten z.B. man. Dies w\"urde folgenderma\ss en durchgef\"uhrt: diff --git a/flash-memory/mtd/handout_mtd_de.tex b/flash-memory/mtd/handout_mtd_de.tex index 15c642f..2a304e1 100644 --- a/flash-memory/mtd/handout_mtd_de.tex +++ b/flash-memory/mtd/handout_mtd_de.tex @@ -4,92 +4,92 @@ \subsubsection{Was sind Memory Technology Devices?} -Prinzipiell kann jedes Stück Speicher als MTD dargestellt werden, +Prinzipiell kann jedes St\"uck Speicher als MTD dargestellt werden, es gibt sogar Treiber, die einfach einen RAM-Bereich exportieren. Unter Linux versteht man aber unter MTD normalerweise Flash-Speicher -in ihren unterschiedlichen Ausprägungen, beispielsweise NAND, NOR, DataFlash -oder OneNAND. Dabei werden Flash-spezifische Eigenschaften berücksichtigt, +in ihren unterschiedlichen Auspr\"agungen, beispielsweise NAND, NOR, DataFlash +oder OneNAND. Dabei werden Flash-spezifische Eigenschaften ber\"ucksichtigt, wie zum Beispiel Hard- und Software-ECC oder die Tatsache, dass diese -Chips nur Eraseblock-weise gelöscht werden können. +Chips nur Eraseblock-weise gel\"oscht werden k\"onnen. Die Art, wie der Chip an den Prozessor angeschlossen ist, spielt dabei -keine Rolle. Der Kernel unterstützt direkt am Bus angeschlossene +keine Rolle. Der Kernel unterst\"utzt direkt am Bus angeschlossene NOR-Bausteine genauso wie NAND-Chips am NAND-Controller oder SPI-Flash-Chips, die mit einem SPI-Bus verbunden sind. -\emph{Nicht} zu den MTD gehören USB-Sticks, SD-Karten oder ähnliche Geräte. +\emph{Nicht} zu den MTD geh\"oren USB-Sticks, SD-Karten oder \"ahnliche Ger\"ate. Diese enthalten zwar auch NAND-Flash, dies wird aber bereits innerhalb -des Geräts von einem eingebauten Controller verwaltet und erscheint für +des Ger\"ats von einem eingebauten Controller verwaltet und erscheint f\"ur den Kernel als normales Block-Device (wie eine Festplatte). NAND-typische -Eigenschaften wie die Größe eines Eraseblocks bleiben dem Kernel unbekannt. +Eigenschaften wie die Gr\"o\ss e eines Eraseblocks bleiben dem Kernel unbekannt. \subsubsection{Das MTD-Subsystem im Kernel} -Wie im Linux-Kernel üblich, werden die Treiber gleichartiger Geräte von -einem eigenen Subsystem verwaltet. Diese Vorgehensweise ermöglicht eine -einheitliche Schnittstelle dieser Geräte, ohne dass sich die einzelnen -Treiber darum kümmern müssten. Ausserdem vereinfacht es die Entwicklung +Wie im Linux-Kernel \"ublich, werden die Treiber gleichartiger Ger\"ate von +einem eigenen Subsystem verwaltet. Diese Vorgehensweise erm\"oglicht eine +einheitliche Schnittstelle dieser Ger\"ate, ohne dass sich die einzelnen +Treiber darum k\"ummern m\"ussten. Ausserdem vereinfacht es die Entwicklung von Treibern, da ihre Struktur vorgegeben ist, und sie sich nicht mehr um immer wiederkehrenden generischen Code oder das Interface zum -Userspace kümmern müssen. +Userspace k\"ummern m\"ussen. \paragraph{Was das MTD-Subsystem im Kernel macht...} -Das MTD-Subsystem verwaltet zunächst die physikalische Struktur eines +Das MTD-Subsystem verwaltet zun\"achst die physikalische Struktur eines Chips, kennt also z.B. dessen Zusammensetzung aus einer gewissen Anzahl -von Eraseblöcken bestimmter Größe, wobei jeder Eraseblock wiederum -aus Pages bestimmter Größe bestehen kann (NAND). +von Erasebl\"ocken bestimmter Gr\"o\ss e, wobei jeder Eraseblock wiederum +aus Pages bestimmter Gr\"o\ss e bestehen kann (NAND). -Jeder Chip kann wiederum in mehrere Partitionen aufgeteilt werden. Für +Jeder Chip kann wiederum in mehrere Partitionen aufgeteilt werden. F\"ur jede Partition legt das MTD-Subsystem ein eigenes Device an, also bei drei Partitionen \cmd{/dev/mtd0}, \cmd{/dev/mtd1} und \cmd{/dev/mtd2}. -Für den Anwender ergibt sich hier bereits die erste Abstrahierung, da er +F\"ur den Anwender ergibt sich hier bereits die erste Abstrahierung, da er nicht mehr wissen muss, ob hinter diesen Devices NAND oder NOR steckt, oder ob es sich um einen oder mehrere Chips handelt. Anhand dieser Device-Dateien kann jetzt auf die einzelnen Partitionen -zugegriffen werden. Dabei können Datenblöcke gelesen und geschrieben -werden, ausserdem können Eraseblöcke gelöscht werden. +zugegriffen werden. Dabei k\"onnen Datenbl\"ocke gelesen und geschrieben +werden, ausserdem k\"onnen Erasebl\"ocke gel\"oscht werden. \paragraph{...und was das MTD-Subsystem \emph{nicht} macht...} -Das MTD-Subsystem wurde bewusst als sehr dünner Abstraktions-Layer +Das MTD-Subsystem wurde bewusst als sehr d\"unner Abstraktions-Layer angelegt. Es geht lediglich um die einheitliche Schnittstelle und den einfachen Zugriff auf den Flash-Speicher. Aufwendigere Techniken werden je nach Anwendung von anderen Teilen des Kernels erledigt. -So verfügt ein mtd-Device weder über ein Dateisystem noch über +So verf\"ugt ein mtd-Device weder \"uber ein Dateisystem noch \"uber Wear-Leveling. Bad Blocks werden zwar unterschieden, der Anwender wird aber nicht daran gehindert, dennoch in diese zu schreiben. Ausser der NAND-eigenen ECC-Fehlerkorrektur gibt es keine weiteren -Schutzmechanismen, falls beim Schreiben der Strom ausfällt, gehen +Schutzmechanismen, falls beim Schreiben der Strom ausf\"allt, gehen Daten verloren. \paragraph{Erweiterungen} -Aus historischen Gründen verfügt der Kernel noch über den \cmd{mtdblock}- -Treiber. Dieser emuliert für ein mtd-Device \cmd{/dev/mtd0} ein -zugehöriges Block-Device \cmd{/dev/mtdblock0}. Da es sich dabei um ein -normales Blockdevice handelt, können auch normale Dateisysteme wie -ext2 oder FAT aufgebracht werden. Ausserdem kümmert sich \cmd{mtdblock} -beim Schreiben um das Löschen der entsprechenden Eraseblocks. +Aus historischen Gr\"unden verf\"ugt der Kernel noch \"uber den \cmd{mtdblock}- +Treiber. Dieser emuliert f\"ur ein mtd-Device \cmd{/dev/mtd0} ein +zugeh\"origes Block-Device \cmd{/dev/mtdblock0}. Da es sich dabei um ein +normales Blockdevice handelt, k\"onnen auch normale Dateisysteme wie +ext2 oder FAT aufgebracht werden. Ausserdem k\"ummert sich \cmd{mtdblock} +beim Schreiben um das L\"oschen der entsprechenden Eraseblocks. -Da \cmd{mtdblock} aber weder Wear-Leveling noch Schutzmassnahmen einführt, -und ausserdem vor allem durch schlechte Performance auffällt, kann von +Da \cmd{mtdblock} aber weder Wear-Leveling noch Schutzmassnahmen einf\"uhrt, +und ausserdem vor allem durch schlechte Performance auff\"allt, kann von seinem Einsatz nur abgeraten werden. -Ähnliches gilt für die ebenfalls vorhandenen Flash-Translation-Layer (FTL). +\"Ahnliches gilt f\"ur die ebenfalls vorhandenen Flash-Translation-Layer (FTL). Obwohl diese teilweise bessere Features mitbringen, gelten sie mangels Interesse als veraltet und schlecht gewartet. -Durch die Einführung von UBI und ubifs sind derartige MTD-Erweiterungen -für die meisten Anwendungen schlicht überflüssig geworden. +Durch die Einf\"uhrung von UBI und ubifs sind derartige MTD-Erweiterungen +f\"ur die meisten Anwendungen schlicht \"uberfl\"ussig geworden. \subsubsection{MTD-Tools} -Um auf mtd-Devices zugreifen zu können, haben die MTD-Entwickler eine Reihe +Um auf mtd-Devices zugreifen zu k\"onnen, haben die MTD-Entwickler eine Reihe von Tools entwickelt, die von den meisten Distributionen als Paket bereit gestellt werden. Unter Debian installiert man die Tools beispielsweise mit @@ -97,14 +97,14 @@ gestellt werden. Unter Debian installiert man die Tools beispielsweise mit aptitude install mtd-utils \end{lstlisting} -Hier eine Übersicht über die wichtigsten Befehle: +Hier eine \"Ubersicht \"uber die wichtigsten Befehle: -Löschen einer Partition: +L\"oschen einer Partition: \begin{lstlisting} flash_eraseall /dev/mtd0 \end{lstlisting} -Löschen einer Partition, gleichzeitig jffs2-Dateisystem aufbringen: +L\"oschen einer Partition, gleichzeitig jffs2-Dateisystem aufbringen: \begin{lstlisting} flash_eraseall -j /dev/mtd0 \end{lstlisting} @@ -116,7 +116,7 @@ nandwrite -p /dev/mtd0 myimage.bin \emph{Beachte:} \cmd{nandwrite} ist das einzige Tool, mit dem man unter Beachtung von Bad Blocks direkt in ein mtd-Device schreiben kann! Wenn man mit konventionellen Tools wie \cmd{dd} in ein mtd-Device schreibt, so werden -auch Bad Blocks beschrieben, ohne dass dies zu einem Fehler führen würde! +auch Bad Blocks beschrieben, ohne dass dies zu einem Fehler f\"uhren w\"urde! Daten aus einer Partition lesen: \begin{lstlisting} @@ -127,6 +127,6 @@ Startadresse 0x10000. Die Daten werden als lesbarer Hexdump (-p) in der Datei \cmd{data.txt} gespeichert. \emph{Hinweis:} Alle diese Tools kennen die Option \cmd{--help}, die alle -verfügbaren Optionen auflistet und kurz erläutert. +verf\"ugbaren Optionen auflistet und kurz erl\"autert. \input{tailhandout} diff --git a/flash-memory/ubi/handout_ubi_de.tex b/flash-memory/ubi/handout_ubi_de.tex index e8402aa..a673a43 100644 --- a/flash-memory/ubi/handout_ubi_de.tex +++ b/flash-memory/ubi/handout_ubi_de.tex @@ -4,45 +4,45 @@ \subsubsection{Was ist UBI?} -UBI kann am ehesten als Logical Volume Manager (LVM) für mtd-Devices -bezeichnet werden. Beim Start scant UBI das mtd-Device und baut eine -Liste der vorhandenen Eraseblöcke auf. Dabei werden auch Bad Blocks +UBI kann am ehesten als Logical Volume Manager (LVM) f\"ur mtd-Devices +bezeichnet werden. Beim Start scanned UBI das mtd-Device und baut eine +Liste der vorhandenen Erasebl\"ocke auf. Dabei werden auch Bad Blocks richtig behandelt, da das MTD-Subsystem, auf dem UBI aufsetzt, diese bereits erkennt. -Dieser Gesamtvorrat an physikalischen Eraseblöcken wird jetzt im -nächsten Schritt an sogenannte UBI-Volumes verteilt. +Dieser Gesamtvorrat an physikalischen Erasebl\"ocken wird jetzt im +n\"achsten Schritt an sogenannte UBI-Volumes verteilt. \subsubsection{UBI-Volumes} UBI-Volumes entsprechen etwa den Partitionen anderer Systeme. Der von -einem mtd-Device bereitgestellte Speicher wird also in mehrere unabhängige +einem mtd-Device bereitgestellte Speicher wird also in mehrere unabh\"angige Einheiten aufgeteilt. Im Vergleich zu den Partitionen, die das MTD-Subsystem auf einem Flash anlegen kann, sind UBI-Volumes aber erheblich -leistungsfähiger und flexibler. Aus diesem Grund empfiehlt es sich, so -wenig wie möglich mtd-Partitionen anzulegen, und UBI eine möglichst große -Partition zur Verwaltung zu übergeben. +leistungsf\"ahiger und flexibler. Aus diesem Grund empfiehlt es sich, so +wenig wie m\"oglich mtd-Partitionen anzulegen, und UBI eine m\"oglichst gro\ss e +Partition zur Verwaltung zu \"ubergeben. MTD-Partitionen haben eine strikt festgelegte Zuordnung von physikalischen -Eraseblöcken zu Partitionen. UBI kann dagegen Eraseblöcke bei Bedarf +Erasebl\"ocken zu Partitionen. UBI kann dagegen Erasebl\"ocke bei Bedarf beliebig zwischen den Volumes umverteilen. Dies geschieht beispielsweise -beim Wear-Leveling, das UBI ebenfalls durchführt. Ebenso können defekte -Eraseblöcke durch andere Blöcke ersetzt werden. +beim Wear-Leveling, das UBI ebenfalls durchf\"uhrt. Ebenso k\"onnen defekte +Erasebl\"ocke durch andere Bl\"ocke ersetzt werden. Durch den von UBI verwendeten Algorithmus ist es selbst beim Neuanlegen -eines Volumes kaum vorhersagbar, welche physikalischen Eraseblöcke es auf -dem Flash belegt. Während eine MTD-Partition immer in denselben -aufeinanderfolgenden Blöcken liegt, ändert sich die Zuordnung von -physikalischen Eraseblöcken des Flash zu logischen Eraseblöcken des +eines Volumes kaum vorhersagbar, welche physikalischen Erasebl\"ocke auf +dem Flash es belegt. W\"ahrend eine MTD-Partition immer in denselben +aufeinanderfolgenden Bl\"ocken liegt, \"andert sich die Zuordnung von +physikalischen Erasebl\"ocken des Flash zu logischen Erasebl\"ocken des Volumes im laufenden Betrieb dynamisch. Ein UBI-Volume mit drei -Eraseblöcken kann also durchaus die physikalischen Blöcke 814, 27 und 1013 belegen. +Erasebl\"ocken kann also durchaus die Bl\"ocke 814, 27 und 1013 belegen. Aus diesem Ansatz ergibt sich auch der Name \emph{Unsorted Block Images}. \emph{Hinweis:} Auf klassischen Festplatten wird ein solches Verhalten -als \emph{Fragmentierung} bezeichnet und ist dort unerwünscht, da eine +als \emph{Fragmentierung} bezeichnet und ist dort unerw\"unscht, da eine mechanische Platte signifikante Seek-Zeiten aufweist. Man versucht dort, -Daten möglichst in aufeinander folgenden Blöcken zu speichern, um zu +Daten m\"oglichst in aufeinander folgenden Bl\"ocken zu speichern, um zu verhindern, dass der mechanische Schreib-/Lesekopf von einem Ende der Platte zum anderen bewegt werden muss. Auf Flash-Speichern gibt es keine Seek-Zeiten, was UBI hier zugunsten eines auf Flash optimierten Designs @@ -50,38 +50,38 @@ ausnutzt. \paragraph{Statische Volumes} -Statische Volumes sind für Anwendungen gedacht, die kein Dateisystem -benötigen. Ein praktisches Beispiel ist ein kleines Volume, das lediglich einen -Kernel enthält, der vom Bootloader geladen und gestartet wird. Mit einem +Statische Volumes sind f\"ur Anwendungen gedacht, die kein Dateisystem +ben\"otigen. Ein praktisches Beispiel ist ein kleines Volume, das lediglich einen +Kernel enth\"alt, der vom Bootloader geladen und gestartet wird. Mit einem statischen Volume muss der Bootloader keinerlei Dateisystem implementieren. Er muss lediglich aus den UBI-Headern herausfinden, welche physikalischen -Eraseblöcke zu dem statischen Volume gehören. Ausserdem erfährt er von UBI, -wie viele Bytes tatsächlich durch Daten belegt sind. Er lädt diese Daten, +Erasebl\"ocke zu dem statischen Volume geh\"oren. Ausserdem erf\"ahrt er von UBI, +wie viele Bytes tats\"achlich durch Daten belegt sind. Er l\"adt diese Daten, im Beispiel einen Kernel, ins RAM und springt sie an. Dies ist mit relativ -wenig Code (einige kB) möglich. +wenig Code (einige kB) m\"oglich. Statische Volumes enthalten also immer nur einen einzigen Datenblock, der in einem Vorgang geschrieben werden muss. \paragraph{Dynamische Volumes} -Dynamische Volumes sind dafür gedacht, ein Dateisystem zu enthalten. -Man verwendet sie also beispielsweise für ein Root-Filesystem oder für -Volumes, die Nutzerdaten enthalten. +Dynamische Volumes sind daf\"ur gedacht, ein Dateisystem zu enthalten. +Man verwendet sie also beispielsweise f\"ur ein Root-Filesystem oder f\"ur +Volumes, die Nutzerdaten enthalten. Dynamische Volumes verwendet man am Besten mit dem Dateisystem ubifs. \paragraph{UBIGLUEBI} -UBIGLUEBI ist ein Aufsatz auf UBI, der für jedes Volume wieder ein -mtd-Device bereitstellt. Dies klingt zunächst überraschend, da UBI ja schon -auf einem mtd-Device aufsetzt. Der Hintergrund ist, dass ältere -Flash-Dateisysteme wie jffs2 ein mtd-Device benötigen. Um deren Einsatz -zu ermöglichen, wurde dieser Zusatz geschaffen. +UBIGLUEBI ist ein Aufsatz auf UBI, der f\"ur jedes Volume wieder ein +mtd-Device bereitstellt. Dies klingt zun\"achst \"uberraschend, da UBI ja schon +auf einem mtd-Device aufsetzt. Der Hintergrund ist, dass \"altere +Flash-Dateisysteme wie jffs2 ein mtd-Device ben\"otigen. Um deren Einsatz +zu erm\"oglichen, wurde dieser Zusatz geschaffen. Heute gibt es ubifs, das direkt auf UBI aufsetzt und folglich kein -mtd-Device benötigt. Da ubifs ohnehin in allen Bereichen deutliche Vorteile -gegenüber jffs2 hat, wird UBIGLUEBI in der Regel nicht mehr benötigt. +mtd-Device ben\"otigt. Da ubifs ohnehin in allen Bereichen deutliche Vorteile +gegen\"uber jffs2 hat, wird UBIGLUEBI in der Regel nicht mehr ben\"otigt. \includegraphics[width=8cm]{images/ubi-big-picture.png} @@ -145,7 +145,7 @@ aptitude install mtd-utils Hier die wichtigsten UBI-Aktionen in Kurzform: -Die Kontrolle über ein mtd-Device an UBI übertragen: +Die Kontrolle \"uber ein mtd-Device an UBI \"ubertragen: \begin{lstlisting} ubiattach /dev/ubi_ctrl -m 2 \end{lstlisting} @@ -155,8 +155,8 @@ Ein Volume anlegen: \begin{lstlisting} ubimkvol /dev/ubi0 -s 3MiB -t static -N kernel -n 1 \end{lstlisting} -Hier wird ein 3MiB großes statisches Volume mit dem Namen \cmd{kernel} -angelegt. Das Volume erhält die Nummer 1. +Hier wird ein 3MiB gro\ss es statisches Volume mit dem Namen \cmd{kernel} +angelegt. Das Volume erh\"alt die Nummer 1. Daten in ein statisches Volume schreiben: \begin{lstlisting} @@ -165,21 +165,21 @@ ubiupdatevol /dev/ubi0_1 zImage Die Daten aus der Datei \cmd{zImage} werden in das statische Volume mit der Nummer 1 geschrieben. -Natürlich lassen sich komplette Volumes auch wieder entfernen: +Nat\"urlich lassen sich komplette Volumes auch wieder entfernen: \begin{lstlisting} ubirmvol/dev/ubi0 -n 1 \end{lstlisting} Das Volume mit der Nummer 1 wird entfernt. Der mit Abstand aufwendigste Befehl ist \cmd{ubinize}. Damit lassen sich -vollständige UBI-Images für ein mtd-Device anfertigen. Diese können -anschließend mit \cmd{nandwrite} in das mtd-Device geschrieben werden. -Alternativ kann das Image natürlich auch mit einem geeigneten JTAGer -in das Flash übertragen werden. Da \cmd{ubinize} sehr vielseitig ist und -relativ viele Flash- und Layout-Parameter berücksichtigt werden müssen, +vollst\"andige UBI-Images f\"ur ein mtd-Device anfertigen. Diese k\"onnen +anschlie\ss end mit \cmd{nandwrite} in das mtd-Device geschrieben werden. +Alternativ kann das Image nat\"urlich auch mit einem geeigneten JTAGer +in das Flash \"ubertragen werden. Da \cmd{ubinize} sehr vielseitig ist und +relativ viele Flash- und Layout-Parameter ber\"ucksichtigt werden m\"ussen, kann hier nur ein einfaches Beispiel gegeben werden. -Zunächst ist eine Konfigurationsdatei erforderlich, in der die einzelnen +Zun\"achst ist eine Konfigurationsdatei erforderlich, in der die einzelnen Volumes sowie die in ihnen unterzubringenden Images beschrieben werden. Diese Datei folgt in ihrer Syntax dem bekannten INI-Format. Ein Volume wird beispielsweise so angegeben: @@ -202,11 +202,11 @@ einem Befehl erzeugen, der etwa so aussieht: \begin{lstlisting} ubinize -o ubi.img -p 128KiB -m 2048 -s 512 ubi-cfg.ini \end{lstlisting} -Im Beispiel wird eine Eraseblock-Größe von 128k angegeben, ausserdem eine -Pagegröße von 2048 Bytes sowie eine Subpage-Größe von 512 Bytes. Das +Im Beispiel wird eine Eraseblock-Gr\"o\ss e von 128k angegeben, ausserdem eine +Pagegr\"o\ss e von 2048 Bytes sowie eine Subpage-Gr\"o\ss e von 512 Bytes. Das fertige Image landet in der Datei \cmd{ubi.img}. -Weitere Informationen sind unter folgender URL erhältlich: +Weitere Informationen sind unter folgender URL erh\"altlich: \begin{lstlisting} http://www.linux-mtd.infradead.org/doc/general.html diff --git a/kernel-devel/uio-driver/handout_uio-driver_de.tex b/kernel-devel/uio-driver/handout_uio-driver_de.tex index f25b538..0266261 100644 --- a/kernel-devel/uio-driver/handout_uio-driver_de.tex +++ b/kernel-devel/uio-driver/handout_uio-driver_de.tex @@ -2,65 +2,65 @@ \subsection{Linux-Treiber im Userspace} -Das ab Linux 2.6.23 im stabilen Kernel verfügbare Userspace-I/O-Framework -(UIO) ermöglicht, bestimmte Treiber fast vollständig in den Userspace zu +Das ab Linux 2.6.23 im stabilen Kernel verf\"ugbare Userspace-I/O-Framework +(UIO) erm\"oglicht, bestimmte Treiber fast vollst\"andig in den Userspace zu verlagern. Dies vereinfacht die Entwicklung und Wartung von Treibern, -außerdem ergeben sich Möglichkeiten, die besonders Industriebetrieben +au\ss erdem ergeben sich M\"oglichkeiten, die besonders Industriebetrieben entgegen kommen. -Eine im Automatisierungsbereich tätige Firma hat eine PCI-I/O-Karte +Eine im Automatisierungsbereich t\"atige Firma hat eine PCI-I/O-Karte entwickelt. Sie soll in einer unter Linux laufenden Maschinensteuerung eingesetzt werden. Ein Linux-Kerneltreiber muss her. Kein Problem, denkt -man sich. Immerhin stehen sowohl der Kernel-Sourcecode als auch die nötigen -Entwicklungstools frei zur Verfügung. So oder so ähnlich hat schon so manche +man sich. Immerhin stehen sowohl der Kernel-Sourcecode als auch die n\"otigen +Entwicklungstools frei zur Verf\"ugung. So oder so \"ahnlich hat schon so manche Linux-Horror-Story begonnen. -Trotz benutzerfreundlicher Kernel-Subsysteme und Unterstützung durch -Mailinglisten bedeutet das Schreiben eines Kerneltreibers für Linux-Einsteiger -eine nicht zu unterschätzende Einarbeitungszeit. Industrielle I/O-Hardware ist +Trotz benutzerfreundlicher Kernel-Subsysteme und Unterst\"utzung durch +Mailinglisten bedeutet das Schreiben eines Kerneltreibers f\"ur Linux-Einsteiger +eine nicht zu untersch\"atzende Einarbeitungszeit. Industrielle I/O-Hardware ist oft so speziell, dass die Subsysteme des Kernels dem Programmierer gerade einmal -das Erkennen der PCI-Karte abnehmen können. Gleichzeitig verfügen solche Karten -oft über sehr komplexe Funktionen, so dass der Treiber immer umfangreicher wird. +das Erkennen der PCI-Karte abnehmen k\"onnen. Gleichzeitig verf\"ugen solche Karten +oft \"uber sehr komplexe Funktionen, so dass der Treiber immer umfangreicher wird. Treibercode mit mehreren tausend Codezeilen ist keine Seltenheit. -Doch auch wenn diese Hürde genommen, der Treiber erfolgreich debugged und -getestet wurde, gibt es ein noch größeres Problem: Die Wartung des Treibers. -Denn ein so großer Treiber verwendet zweifellos eine große Zahl interner +Doch auch wenn diese H\"urde genommen, der Treiber erfolgreich debugged und +getestet wurde, gibt es ein noch gr\"o\ss eres Problem: Die Wartung des Treibers. +Denn ein so gro\ss er Treiber verwendet zweifellos eine gro\ss e Zahl interner Kernel-Funktionen und -Makros. Dieses Kernel-interne API ist stets in Bewegung. -Wer einen Treiber für 2.6.30 geschrieben hat, hat keinerlei Garantie, dass der +Wer einen Treiber f\"ur 2.6.30 geschrieben hat, hat keinerlei Garantie, dass der unter 2.6.31 noch fehlerfrei kompiliert. Wer seinen Code mehrere Kernel-Versionen -lang liegen lässt und dann upgraden will, hat höchst wahrscheinlich ein paar +lang liegen l\"asst und dann upgraden will, hat h\"ochst wahrscheinlich ein paar unerfreuliche Tage vor sich. -Das zuletzt genannte Problem löst sich in Luft auf, wenn es gelingt, die +Das zuletzt genannte Problem l\"ost sich in Luft auf, wenn es gelingt, die Kernel-Entwickler, an der Spitze Linus Torvalds, dazu zu bewegen, den Code in den stabilen Mainline-Kernel aufzunehmen. Denn dann sind die Entwickler, die -etwas am internen API ändern, verpflichtet, für die Anpassung aller betroffenen -Module zu sorgen. Für unsere Automatisierungsfirma würde das bedeuten, dass die -Linux-Community ihnen gratis diese Wartungsarbeit abnehmen würde. Sie und ihre -Kunden könnten immer die neueste Kernelversion verwenden und würden ihren Treiber -kompilierfähig vorfinden. - -Leider ist dies aus mehreren Gründen oft nicht machbar. Erstens werden die -Kernel-Entwickler die Aufnahme eines großen Treibers, der nicht von allgemeinem -Interesse ist, schlicht verweigern. Der Umfang des Kernelcodes würde sonst ins +etwas am internen API \"andern, verpflichtet, f\"ur die Anpassung aller betroffenen +Module zu sorgen. F\"ur unsere Automatisierungsfirma w\"urde das bedeuten, dass die +Linux-Community ihnen gratis diese Wartungsarbeit abnehmen w\"urde. Sie und ihre +Kunden k\"onnten immer die neueste Kernelversion verwenden und w\"urden ihren Treiber +kompilierf\"ahig vorfinden. + +Leider ist dies aus mehreren Gr\"unden oft nicht machbar. Erstens werden die +Kernel-Entwickler die Aufnahme eines gro\ss en Treibers, der nicht von allgemeinem +Interesse ist, schlicht verweigern. Der Umfang des Kernelcodes w\"urde sonst ins Unermessliche wachsen. Zweitens geht der Aufnahme von Code in den Mainline-Kernel -gewöhnlich eine langwierige Review-Prozedur voraus. Dabei wird nicht nur +gew\"ohnlich eine langwierige Review-Prozedur voraus. Dabei wird nicht nur Coding-Style begutachtet, es kann sich durchaus auch um Kritik an grundlegenden Vorgehensweisen handeln. Erst wenn alle Kritiker zufrieden gestellt sind, wird -der Code in den Kernel aufgenommen. Darüber können Wochen vergehen. Die wenigsten +der Code in den Kernel aufgenommen. Dar\"uber k\"onnen Wochen vergehen. Die wenigsten Industriebetriebe genehmigen ihren Programmierern diesen Zusatzaufwand, da der -Treiber in ihrer Maschine ja schon läuft. +Treiber in ihrer Maschine ja schon l\"auft. Drittens haben manche Firmen Probleme mit der GPL. Code, der im Kernel -einkompiliert wird, muss dieser Lizenz genügen, das heißt, der Sourcecode muss -öffentlich zugänglich sein. Firmen haben in der Vergangenheit zahlreiche +einkompiliert wird, muss dieser Lizenz gen\"ugen, das hei\ss t, der Sourcecode muss +\"offentlich zug\"anglich sein. Firmen haben in der Vergangenheit zahlreiche (meist illegale) Tricks angewandt, um dieser Bedingung der GPL zu entgehen und ihren Kernelcode unter Verschluss zu halten. -\subsubsection{UIO löst Probleme} +\subsubsection{UIO l\"ost Probleme} -Die geschilderte Problematik führte bereits vor längerer Zeit zu Überlegungen, +Die geschilderte Problematik f\"uhrte bereits vor l\"angerer Zeit zu \"Uberlegungen, zumindest Teile eines Treibers in den Userspace zu verlagern. I/O-Hardware besteht in der Regel aus einem Speicherbereich, in dem sich RAM oder Register befinden. Linux ist von Haus aus in der Lage, einen solchen Speicherbereich per @@ -69,87 +69,87 @@ der Hardware erreichen. Dies ist aber erst die halbe Miete: In der Regel erzeugen I/O-Karten Interrupts, und diese lassen sich nur im Kernel bearbeiten. Ausserdem muss man in einem allgemein verwendbaren System der Tatsache Rechnung tragen, dass eventuell mehrere (gleiche oder verschiedene) I/O-Karten -im System vorhanden sein können. +im System vorhanden sein k\"onnen. -Das Userspace-I/O-Framework (UIO) löst diese Probleme einfach und elegant. -Das für den Treiber immer noch benötigte Kernelmodul beschränkt sich auf einen +Das Userspace-I/O-Framework (UIO) l\"ost diese Probleme einfach und elegant. +Das f\"ur den Treiber immer noch ben\"otigte Kernelmodul beschr\"ankt sich auf einen minimalen Interrupt-Handler sowie das Anmelden des Treibers beim UIO-Framework. Letzteres erzeugt ein Device-File unter /dev sowie einige dokumentierte Standardfiles im sysfs unter /sys/class/uio. Ausserdem stellt das -UIO-Framework bereits die für den Zugriff auf das Device-File benötigten -Funktionen wie \cmd{open()}, \cmd{read()} und \cmd{mmap()} zur Verfügung. Im +UIO-Framework bereits die f\"ur den Zugriff auf das Device-File ben\"otigten +Funktionen wie \cmd{open()}, \cmd{read()} und \cmd{mmap()} zur Verf\"ugung. Im kundenspezifischen Kerneltreiber wird lediglich eine Struktur vom Typ -\cmd{struct uio\_info} mit einigen Informationen gefüllt und damit die Funktion +\cmd{struct uio\_info} mit einigen Informationen gef\"ullt und damit die Funktion \cmd{uio\_register\_device()} aufgerufen. Den Rest erledigt das Framework. Durch dieses Design kann das hardwarespezifische Kernelmodul sehr klein -ausfallen: das seit Kernel 2.6.23 enthaltene Modul für eine PCI-Feldbuskarte +ausfallen: das seit Kernel 2.6.23 enthaltene Modul f\"ur eine PCI-Feldbuskarte (Hilscher CIF) besteht aus gerade einmal 156 Zeilen, inklusive Leerzeilen und -Kommentaren. Durch die sehr überschaubare Codegröße ist ein solches Modul schnell -geschrieben, übersichtlich, wenig fehleranfällig, leicht wartbar und kann +Kommentaren. Durch die sehr \"uberschaubare Codegr\"o\ss e ist ein solches Modul schnell +geschrieben, \"ubersichtlich, wenig fehleranf\"allig, leicht wartbar und kann wesentlich leichter in den Mainline-Kernel integriert werden. Der Review-Prozess -ist viel einfacher, da auch Kernelentwickler, die nicht über die passende -Hardware verfügen, das Modul bezüglich Fehlerfreiheit beurteilen können. +ist viel einfacher, da auch Kernelentwickler, die nicht \"uber die passende +Hardware verf\"ugen, das Modul bez\"uglich Fehlerfreiheit beurteilen k\"onnen. Nach dem Laden des Kernelmoduls kann man vom Userspace aus das Device-File -(z.B. \cmd{/dev/uio0}) öffnen und sich per \cmd{mmap()}-Aufruf Zugriff auf -den Speicher der Hardware verschaffen. Man wird zunächst durch geeignetes +(z.B. \cmd{/dev/uio0}) \"offnen und sich per \cmd{mmap()}-Aufruf Zugriff auf +den Speicher der Hardware verschaffen. Man wird zun\"achst durch geeignetes Beschreiben von Registern die Hardware initialisieren, so dass sie die -gewünschte Funktion ausführt und Interrupts generiert. Auf Interrupts wartet +gew\"unschte Funktion ausf\"uhrt und Interrupts generiert. Auf Interrupts wartet man, indem man mit einem blockierenden \cmd{read()}-Aufruf einen 32-bit-Wert -aus dem Device-File liest. Der Aufruf kehrt zurück, sobald ein Interrupt +aus dem Device-File liest. Der Aufruf kehrt zur\"uck, sobald ein Interrupt eintrifft. Der gelesene 32-bit-Wert gibt die Gesamtzahl der bisher -aufgetretenen Interrupts an. Der Wert sollte idealerweise um eins größer -sein als beim letzten Mal. Ist er noch größer, so hat man Interrupts verpasst. +aufgetretenen Interrupts an. Der Wert sollte idealerweise um eins gr\"o\ss er +sein als beim letzten Mal. Ist er noch gr\"o\ss er, so hat man Interrupts verpasst. Man beachte, dass der Interrupt-Handler im Kernelmodul den Interrupt bereits quittiert haben muss. Im Fall eines pegelgetriggerten Interrupts, wie er bei -PCI-Karten üblich ist, würde sich der Rechner sonst sang- und klanglos -aufhängen. Bei Rückkehr des blockierenden \cmd{read()}-Aufrufs kann man sich -also darauf beschränken, Daten zu lesen und zu schreiben, Statusregister zu -lesen, neue Parameter zu setzen oder ähnliche Aufgaben, die beim Auftreten +PCI-Karten \"ublich ist, w\"urde sich der Rechner sonst sang- und klanglos +aufh\"angen. Bei R\"uckkehr des blockierenden \cmd{read()}-Aufrufs kann man sich +also darauf beschr\"anken, Daten zu lesen und zu schreiben, Statusregister zu +lesen, neue Parameter zu setzen oder \"ahnliche Aufgaben, die beim Auftreten eines Interrupts anfallen. Falls die entsprechende Routine damit bis zum -Eintreffen des nächsten Interrupts nicht fertig wird, so ist das zumindest -softwaretechnisch kein Problem: Anhand des gelesenen Werts beim nächsten +Eintreffen des n\"achsten Interrupts nicht fertig wird, so ist das zumindest +softwaretechnisch kein Problem: Anhand des gelesenen Werts beim n\"achsten \cmd{read()} erkennen Sie, wie viele Interrupts Sie verpasst haben. \subsubsection{GPL oder nicht GPL} -Der Linux-Kernel einschließlich aller enthaltenen Module ist unter der GPL -lizensiert. Programme im Linux-Userspace unterliegen solchen Einschränkungen -nicht. Das gilt auch für UIO-Treiber. Mit UIO existiert daher erstmals eine -Kernel-Schnittstelle, die es erlaubt, einen interruptfähigen Treiber zu -schreiben, der größtenteils nicht der GPL unterliegt (das kleine Kernelmodul -muss natürlich immer noch GPL-lizensiert werden). Diese Tatsache hat für +Der Linux-Kernel einschlie\ss lich aller enthaltenen Module ist unter der GPL +lizensiert. Programme im Linux-Userspace unterliegen solchen Einschr\"ankungen +nicht. Das gilt auch f\"ur UIO-Treiber. Mit UIO existiert daher erstmals eine +Kernel-Schnittstelle, die es erlaubt, einen interruptf\"ahigen Treiber zu +schreiben, der gr\"o\ss tenteils nicht der GPL unterliegt (das kleine Kernelmodul +muss nat\"urlich immer noch GPL-lizensiert werden). Diese Tatsache hat f\"ur einigen Wirbel in der Linux-Szene gesorgt. Das UIO-Framework wurde von Mitarbeitern der Firma Linutronix entwickelt und an Greg Kroah-Hartman, den Maintainer des Linux driver core, weiter gereicht. Kroah-Hartman versuchte am 13.12.2006 erstmals, UIO im Mainline-Kernel unterzubringen. -Linus Torvalds lehnte die Aufnahme damals ab, hauptsächlich aufgrund von -Missverständnissen bezüglich eines beigefügten Demo-Treibers. In der Folge +Linus Torvalds lehnte die Aufnahme damals ab, haupts\"achlich aufgrund von +Missverst\"andnissen bez\"uglich eines beigef\"ugten Demo-Treibers. In der Folge entstand eine wochenlange Diskussion, die schnell vom eigentlichen Thema -abwich und sich hauptsächlich mit der Lizensierungs-Problematik beschäftigte. +abwich und sich haupts\"achlich mit der Lizensierungs-Problematik besch\"aftigte. Dabei lag es in erster Linie gar nicht in der Absicht der UIO-Entwickler, -proprietäre Treiber zu ermöglichen. Dies ist eigentlich ein Nebeneffekt, der -sich aus der Tatsache ergibt, dass man für Userspace-Software unter Linux seit -eh und je die Lizenz frei wählen darf. Dennoch mag dieser Punkt in einigen -Firmen für Erleichterung sorgen. Wer etwa bestimmtes Know-How in einem FPGA -untergebracht hat, der möchte nicht unter dem Zwang stehen, den Code des -zugehörigen Treibers öffentlich zu machen. Manchmal kann dies sogar durch den -Endkunden vertraglich untersagt sein, zum Beispiel bei Code, der für die -Einhaltung gesetzlich vorgeschriebener Werte sorgt, bei militärischen oder +propriet\"are Treiber zu erm\"oglichen. Dies ist eigentlich ein Nebeneffekt, der +sich aus der Tatsache ergibt, dass man f\"ur Userspace-Software unter Linux seit +eh und je die Lizenz frei w\"ahlen darf. Dennoch mag dieser Punkt in einigen +Firmen f\"ur Erleichterung sorgen. Wer etwa bestimmtes Know-How in einem FPGA +untergebracht hat, der m\"ochte nicht unter dem Zwang stehen, den Code des +zugeh\"origen Treibers \"offentlich zu machen. Manchmal kann dies sogar durch den +Endkunden vertraglich untersagt sein, zum Beispiel bei Code, der f\"ur die +Einhaltung gesetzlich vorgeschriebener Werte sorgt, bei milit\"arischen oder sonst sicherheitsrelevanten Anwendungen. -Bisher waren solche Firmen gezwungen, Codeänderungen durch technische Klimmzüge -zu verhindern, bewusst gegen die GPL zu verstoßen oder ganz auf Linux zu +Bisher waren solche Firmen gezwungen, Code\"anderungen durch technische Klimmz\"uge +zu verhindern, bewusst gegen die GPL zu versto\ss en oder ganz auf Linux zu verzichten. Durch UIO wird an dieser Stelle ein gangbarer und legaler Ausweg geschaffen. \subsubsection{Konventionelle Treiber...} -Bisherige Gerätetreiber sind vollständig im Kernel integriert. Die -Schnittstelle zum Userspace besteht typischerweise aus einer Gerätedatei, auf -die mit den üblichen Funktionen wie \cmd{open()}, \cmd{close()}, \cmd{read()}, +Bisherige Ger\"atetreiber sind vollst\"andig im Kernel integriert. Die +Schnittstelle zum Userspace besteht typischerweise aus einer Ger\"atedatei, auf +die mit den \"ublichen Funktionen wie \cmd{open()}, \cmd{close()}, \cmd{read()}, \cmd{write()} und \cmd{ioctl()} zugegriffen werden kann. \begin{figure}[h] @@ -162,14 +162,14 @@ die mit den üblichen Funktionen wie \cmd{open()}, \cmd{close()}, \cmd{read()}, Alle diese Funktionen -müssen vollständig im Treiber implementiert werden und führen je nach Gerät +m\"ussen vollst\"andig im Treiber implementiert werden und f\"uhren je nach Ger\"at mehr oder weniger komplexe Operationen mit der Hardware aus. Bei industriellen I/O-Karten liegt meist ein Schwerpunkt auf der \cmd{ioctl()}-Funktion. Die Ein- -und Ausgabe-Funktionaltät der Karte ist oft so komplex, dass man sie nicht auf +und Ausgabe-Funktionalt\"at der Karte ist oft so komplex, dass man sie nicht auf einfache \cmd{read()}- und \cmd{write()}-Operationen abbilden kann. Ausserdem haben solche Karten in der Regel zahlreiche Parameter und Optionen, die auf einen bestimmten Wert gesetzt oder ein- und ausgeschaltet werden wollen. -Man findet daher häufig Treiber für derartige Industrie-Karten, die 50 oder +Man findet daher h\"aufig Treiber f\"ur derartige Industrie-Karten, die 50 oder mehr ioctl-Unterfunktionen implementieren. \begin{figure}[h] @@ -179,54 +179,54 @@ mehr ioctl-Unterfunktionen implementieren. \label{img:ioctl} \end{figure} -Dies führt oft dazu, dass letzlich mehr Datenaustausch mit der Karte per -\cmd{ioctl()} abgewickelt wird als über die eigentlich dafür vorgesehenen -\cmd{read()}- und \cmd{write()}-Funktionen. Auch aus Performance-Gründen ist +Dies f\"uhrt oft dazu, dass letzlich mehr Datenaustausch mit der Karte per +\cmd{ioctl()} abgewickelt wird als \"uber die eigentlich daf\"ur vorgesehenen +\cmd{read()}- und \cmd{write()}-Funktionen. Auch aus Performance-Gr\"unden ist diese Vorgehensweise alles Andere als optimal. Wenn beispielsweise \cmd{ioctl()} dazu verwendet wird, einen 32-Bit-Wert in ein Register der -Hardware zu schreiben, dann packt das Anwenderprogramm im Userspace zunächst -den Wert auf den Stack und ruft über die libc \cmd{ioctl()} auf. Per syscall +Hardware zu schreiben, dann packt das Anwenderprogramm im Userspace zun\"achst +den Wert auf den Stack und ruft \"uber die libc \cmd{ioctl()} auf. Per syscall landet der Aufruf im Kernel. Dort sucht das Virtual File System (VFS) den -Pointer auf die für das jeweilige Gerät zuständige \cmd{ioctl()}-Funktion und -ruft diese auf. Da die übergebenen Parameter im User-Speicher liegen, muss sie -die \cmd{ioctl()}-Implementierung zunächst mit Hilfe der Kernel-Funktion +Pointer auf die f\"ur das jeweilige Ger\"at zust\"andige \cmd{ioctl()}-Funktion und +ruft diese auf. Da die \"ubergebenen Parameter im User-Speicher liegen, muss sie +die \cmd{ioctl()}-Implementierung zun\"achst mit Hilfe der Kernel-Funktion \cmd{copy\_from\_user()} in den Kernel-Speicher holen. Jetzt endlich kann der -übergebene Wert in das Hardware-Register geschrieben werden. Falls der Aufruf -auch Werte zurückgeben soll, müssen diese entsprechend erst mit -\cmd{copy\_to\_user()} in den übergebenen Puffer geschrieben werden. +\"ubergebene Wert in das Hardware-Register geschrieben werden. Falls der Aufruf +auch Werte zur\"uckgeben soll, m\"ussen diese entsprechend erst mit +\cmd{copy\_to\_user()} in den \"ubergebenen Puffer geschrieben werden. Letztlich handelt es sich bei einem derartigen Konzept um einen Missbrauch von -\cmd{ioctl()}. Die Funktion war ursprünglich nur dazu gedacht, gelegentlich -einen Parameter einer (Geräte-)Datei zu ändern. Für häufigen, schnellen -Datenaustausch ist sie denkbar ungeeignet und vor allem auch unnötig, wie wir +\cmd{ioctl()}. Die Funktion war urspr\"unglich nur dazu gedacht, gelegentlich +einen Parameter einer (Ger\"ate-)Datei zu \"andern. F\"ur h\"aufigen, schnellen +Datenaustausch ist sie denkbar ungeeignet und vor allem auch unn\"otig, wie wir weiter unten sehen werden. Die Kernel-Entwickler stehen daher einer -\cmd{ioctl()}-basierten Treiberimplementierung äußerst kritisch gegenüber. -Ein Treiber für eine exotische Karte, der 50 neue \cmd{ioctl()}-Funktionen -einführen will, wird wahrscheinlich schon aus diesem Grund nicht in den +\cmd{ioctl()}-basierten Treiberimplementierung \"au\ss erst kritisch gegen\"uber. +Ein Treiber f\"ur eine exotische Karte, der 50 neue \cmd{ioctl()}-Funktionen +einf\"uhren will, wird wahrscheinlich schon aus diesem Grund nicht in den Mainline-Kernel aufgenommen. -Ein weiteres Problem ergibt sich aus der Größe des Treibercodes. Ein paar -tausend (nicht-triviale) Zeilen sind schnell beieinander. Obwohl auch für die -Kernel-Entwicklung zahlreiche mächtige Hilfsmittel zur Fehlersuche existieren, +Ein weiteres Problem ergibt sich aus der Gr\"o\ss e des Treibercodes. Ein paar +tausend (nicht-triviale) Zeilen sind schnell beieinander. Obwohl auch f\"ur die +Kernel-Entwicklung zahlreiche m\"achtige Hilfsmittel zur Fehlersuche existieren, erfordert das Debugging doch erheblich mehr an Spezialwissen als im Userspace. -In einem Kerneltreiber können einfache Fehler den Rechner so lahm legen, dass +In einem Kerneltreiber k\"onnen einfache Fehler den Rechner so lahm legen, dass nur noch der Griff zum Resettaster Rettung bringt. In einem Industriebetrieb -verfügen häufig auch die ansonsten sehr qualifizierten Programmierer nur über -wenig Erfahrung mit Linux-Kernelprogrammierung. Mit den üblicherweise recht -eingeschränkten Ressourcen an Zeit und Personal entstehen dann Treiber, die -ebenso fehlerträchtig wie unübersichtlich sind und keinerlei Chance auf +verf\"ugen h\"aufig auch die ansonsten sehr qualifizierten Programmierer nur \"uber +wenig Erfahrung mit Linux-Kernelprogrammierung. Mit den \"ublicherweise recht +eingeschr\"ankten Ressourcen an Zeit und Personal entstehen dann Treiber, die +ebenso fehlertr\"achtig wie un\"ubersichtlich sind und keinerlei Chance auf Aufnahme in den offiziellen Mainline-Kernel haben. Dadurch haben die -Programmierer dann während der gesamten Laufzeit des Produkts zusätzlich das -Problem, diesen wackligen Treiber out-of-tree warten zu müssen. +Programmierer dann w\"ahrend der gesamten Laufzeit des Produkts zus\"atzlich das +Problem, diesen wackligen Treiber out-of-tree warten zu m\"ussen. \subsubsection{...und UIO-Treiber} -Sieht man sich Gerätetreiber etwas genauer an, so stellt man fest, dass es +Sieht man sich Ger\"atetreiber etwas genauer an, so stellt man fest, dass es stets wiederkehrende Aufgabenstellungen gibt. Zum einen hat die Hardware -einen oder mehrere Speicherbereiche, auf die man zugreifen möchte. Zum +einen oder mehrere Speicherbereiche, auf die man zugreifen m\"ochte. Zum anderen erzeugt die Hardware Interrupts, auf die reagiert werden muss. Das -UIO-Framework enthält den Code für diese Standardaufgaben und vermeidet so, -dass Programmierer ständig ein nicht ganz einfaches Rad neu erfinden müssen. +UIO-Framework enth\"alt den Code f\"ur diese Standardaufgaben und vermeidet so, +dass Programmierer st\"andig ein nicht ganz einfaches Rad neu erfinden m\"ussen. \begin{figure}[h] \centering @@ -235,126 +235,126 @@ dass Programmierer ständig ein nicht ganz einfaches Rad neu erfinden müssen. \label{img:konvtreiber} \end{figure} -Um Speicherbereiche verwenden zu können, muss man dem UIO-Framework lediglich -deren Startadresse und Länge angeben. UIO stellt dann bereits eine -\cmd{mmap()}-Funktion zur Verfügung, die es erlaubt, die Speicherbereiche +Um Speicherbereiche verwenden zu k\"onnen, muss man dem UIO-Framework lediglich +deren Startadresse und L\"ange angeben. UIO stellt dann bereits eine +\cmd{mmap()}-Funktion zur Verf\"ugung, die es erlaubt, die Speicherbereiche in den Userspace zu mappen. Im Falle einer PCI-Karte erhalten Sie die -Informationen über Startadresse und Länge bereits vom PCI-Subsystem. +Informationen \"uber Startadresse und L\"ange bereits vom PCI-Subsystem. Zur Behandlung von Interrupts muss lediglich ein minimaler Interrupt-Handler -geschrieben werden. Um Interrupt-Sharing zu ermöglichen, sollte der Handler -erkennen, ob es die eigene Karte war, die den Interrupt ausgelöst hat. Falls -nein, gibt er einfach IRQ\_NONE zurück. Falls ja, wird er den Interrupt bei -der Hardware quittieren und dafür sorgen, dass die Interrupt-Leitung wieder +geschrieben werden. Um Interrupt-Sharing zu erm\"oglichen, sollte der Handler +erkennen, ob es die eigene Karte war, die den Interrupt ausgel\"ost hat. Falls +nein, gibt er einfach IRQ\_NONE zur\"uck. Falls ja, wird er den Interrupt bei +der Hardware quittieren und daf\"ur sorgen, dass die Interrupt-Leitung wieder ihren inaktiven Zustand annimmt. Auch hier muss man lediglich die Nummer des Interrupts und einen Pointer auf den Handler angeben, den Rest erledigt das Framework. -Zu den weiteren Dienstleistungen des UIO-Frameworks gehört das Anlegen und +Zu den weiteren Dienstleistungen des UIO-Frameworks geh\"ort das Anlegen und Behandeln von Dateien im sysfs. Unter \cmd{/sys/class/uio} finden sich -Informationen zu allen angemeldeten UIO-Geräten. Dazu gehören der Name des -Geräts, Version seines Kernelmoduls, Adressen und Größen seiner -Speicherbereiche, Anzahl aufgetretener Interrupts und Ähnliches. Diese -(dokumentierten) sysfs-Dateien ermöglichen es dem Userspace-Teil des Treibers, -gezielt nach seinem Gerät zu suchen und beispielsweise die Größen der +Informationen zu allen angemeldeten UIO-Ger\"aten. Dazu geh\"oren der Name des +Ger\"ats, Version seines Kernelmoduls, Adressen und Gr\"o\ss en seiner +Speicherbereiche, Anzahl aufgetretener Interrupts und \"Ahnliches. Diese +(dokumentierten) sysfs-Dateien erm\"oglichen es dem Userspace-Teil des Treibers, +gezielt nach seinem Ger\"at zu suchen und beispielsweise die Gr\"o\ss en der Speicherbereiche korrekt zu erfragen, anstatt sich auf fest kodierte Werte zu verlassen. -Insgesamt enthält das UIO-Framework etwa 900 Zeilen nicht-trivialen Code, die -man für eine ähliche Funktionalität sonst selbst schreiben müsste. Dagegen -kommt das zu erstellende gerätespezifische Modul auf etwa 150 Zeilen Code, +Insgesamt enth\"alt das UIO-Framework etwa 900 Zeilen nicht-trivialen Code, die +man f\"ur eine \"ahliche Funktionalit\"at sonst selbst schreiben m\"usste. Dagegen +kommt das zu erstellende ger\"atespezifische Modul auf etwa 150 Zeilen Code, der zudem recht einfach ist und leicht von schon existierenden Treibern abgeleitet werden kann. Dadurch haben auch weniger erfahrene Programmierer -die Chance, ein sauberes, übersichtliches und stabiles Modul für ihre Hardware -zu produzieren. Es bleibt auch jederzeit die Möglichkeit, sich dieses Modul +die Chance, ein sauberes, \"ubersichtliches und stabiles Modul f\"ur ihre Hardware +zu produzieren. Es bleibt auch jederzeit die M\"oglichkeit, sich dieses Modul von einem erfahrenen Dienstleister erstellen zu lassen. Auf diese Weise ist es -möglich, eigene Treiber zu entwickeln, ohne eine einzige Zeile Kernel-Code -schreiben zu müssen. +m\"oglich, eigene Treiber zu entwickeln, ohne eine einzige Zeile Kernel-Code +schreiben zu m\"ussen. -Der ganze Rest, also die komplette eigentliche Funktionalität des Treibers, +Der ganze Rest, also die komplette eigentliche Funktionalit\"at des Treibers, wird im Userspace erledigt. Der Treiber kann als Shared Library, als -Bestandteil eines Anwenderprogramms oder in bester Unix-Manier als Dämon -realisiert werden. Die Programmierer des Treibers benötigen nicht mehr +Bestandteil eines Anwenderprogramms oder in bester Unix-Manier als D\"amon +realisiert werden. Die Programmierer des Treibers ben\"otigen nicht mehr Kenntnisse und Tools, als sie zur Programmierung ihrer Applikation ohnehin -benötigen. +ben\"otigen. Im Beispiel oben haben wir gesehen, welchen Aufwand es bedeutet, einen -einzelnen Wert per \cmd{ioctl()} in ein Hardware-Register zu befördern. Im +einzelnen Wert per \cmd{ioctl()} in ein Hardware-Register zu bef\"ordern. Im Falle von UIO ist diese Operation eine einfache Zuweisung an die betreffende Stelle des gemappten Speichers. Wenn \cmd{a} der Zeiger auf den Speicher ist und an die relative Adresse 1000 der Wert 5 geschrieben werden soll, so schreibt man ohne Umschweife \cmd{a[1000]=5}. Jegliches Hin- und Herkopieren -entfällt, so dass sich bei schnellen Anwendungen ein echter Performance-Vorteil -gegenüber einem Kerneltreiber mit \cmd{ioctl()}-Konzept ergibt. Es ist also -keinesfalls so, dass man für den Userspace-Komfort Geschwindigkeits-Nachteile -in Kauf nehmen müsste. +entf\"allt, so dass sich bei schnellen Anwendungen ein echter Performance-Vorteil +gegen\"uber einem Kerneltreiber mit \cmd{ioctl()}-Konzept ergibt. Es ist also +keinesfalls so, dass man f\"ur den Userspace-Komfort Geschwindigkeits-Nachteile +in Kauf nehmen m\"usste. Was sich ebenfalls verbessert, ist das Handling von Updates. Bei einem reinen -Kernel-Treiber ist ein Update des Kernels oder zumindest der Module nötig, was +Kernel-Treiber ist ein Update des Kernels oder zumindest der Module n\"otig, was in der Regel root-Rechte des Anwenders erfordert und bei Fehlern zu einem -völlig unbrauchbaren System führt. Bei einem UIO-Treiber unterscheidet sich +v\"ollig unbrauchbaren System f\"uhrt. Bei einem UIO-Treiber unterscheidet sich ein Update des Treibers durch nichts von einem Update der Anwender-Applikation. \subsubsection{Wartungsvertrag} -Ein Treiber will gewartet sein. Bei industriellen Geräten findet man oft die -Situation, dass ein Gerät über einen längeren Zeitraum mit der selben -Kernelversion ausgeliefert wird. Möchte man später, etwa nach 6 Monaten oder +Ein Treiber will gewartet sein. Bei industriellen Ger\"aten findet man oft die +Situation, dass ein Ger\"at \"uber einen l\"angeren Zeitraum mit der selben +Kernelversion ausgeliefert wird. M\"ochte man sp\"ater, etwa nach 6 Monaten oder einem Jahr, beispielsweise im Zuge eines allgemeinen Software-Updates auf einen -aktuellen Kernel wechseln, so sind oft deutliche Änderungen am Kerneltreiber -nötig. +aktuellen Kernel wechseln, so sind oft deutliche \"Anderungen am Kerneltreiber +n\"otig. -Konventionelle Treiber beinhalten zwangsläufig viele Aufrufe von internen +Konventionelle Treiber beinhalten zwangsl\"aufig viele Aufrufe von internen Kernelfunktionen. Im Gegensatz zur stabilen syscall-Schnittstelle kann sich -dieses interne Kernel-API jederzeit ändern. Sie müssen damit rechnen, dass -Funktionen, die ihr Treiber verwendet, plötzlich nicht mehr existieren oder -andere Parameter haben. Entsprechend hoch ist der Wartungsaufwand für einen +dieses interne Kernel-API jederzeit \"andern. Sie m\"ussen damit rechnen, dass +Funktionen, die ihr Treiber verwendet, pl\"otzlich nicht mehr existieren oder +andere Parameter haben. Entsprechend hoch ist der Wartungsaufwand f\"ur einen solchen Treiber, wenn er nicht im Mainline-Kernel enthalten ist. -UIO macht ihnen auch hier das Leben leichter. Das Framework übernimmt die -üble Kleinarbeit, die etwa beim Umgang mit sysfs, Interrupt-Handling oder -Memory-Mapping anfällt. Es schirmt sie sozusagen von den wilden Seiten des +UIO macht ihnen auch hier das Leben leichter. Das Framework \"ubernimmt die +\"uble Kleinarbeit, die etwa beim Umgang mit sysfs, Interrupt-Handling oder +Memory-Mapping anf\"allt. Es schirmt sie sozusagen von den wilden Seiten des Kernels ab, indem es ihnen erlaubt, mit etwa einem halben Dutzend einfacher -Funktionen auszukommen. Angesichts der geringen Codegröße eines -UIO-Kernelmoduls sind selbst bei Änderungen an diesen Funktionen die -Wartungsarbeiten sehr überschaubar und schnell ausgeführt. +Funktionen auszukommen. Angesichts der geringen Codegr\"o\ss e eines +UIO-Kernelmoduls sind selbst bei \"Anderungen an diesen Funktionen die +Wartungsarbeiten sehr \"uberschaubar und schnell ausgef\"uhrt. -Betrachtet man als Beispiel den Treiber für die Hilscher CIF-Karte -\cmd{(drivers/uio/uio\_cif.c)}, dann fällt auf, dass für die Einbindung in das +Betrachtet man als Beispiel den Treiber f\"ur die Hilscher CIF-Karte +\cmd{(drivers/uio/uio\_cif.c)}, dann f\"allt auf, dass f\"ur die Einbindung in das UIO-Framework lediglich zwei Funktionen (\cmd{uio\_register\_device} und \cmd{uio\_unregister\_device}) sowie eine Datenstruktur -(\cmd{struct uio\_info}) benötigt werden. Ansonsten werden lediglich 7 +(\cmd{struct uio\_info}) ben\"otigt werden. Ansonsten werden lediglich 7 Funktionen des PCI-Subsystems sowie 6 sonstige Funktionen wie \cmd{kzalloc()} -benutzt. Alle diese Funktionen sind einfach und gängig. Das sie sich ändern, -ist möglich, aber nicht sehr wahrscheinlich. +benutzt. Alle diese Funktionen sind einfach und g\"angig. Das sie sich \"andern, +ist m\"oglich, aber nicht sehr wahrscheinlich. -Dennoch sollten sie den Kernelteil ihres Treibers möglichst nicht ausserhalb +Dennoch sollten sie den Kernelteil ihres Treibers m\"oglichst nicht ausserhalb des offiziellen Mainline-Kernels pflegen wollen. Schreiben sie sauberen Code -entsprechend dem Kernel-Coding-Style und zögern sie nicht, auf der -Linux-Kernel-Mailingliste um die Aufnahme desselben zu bitten. Die Mühe lohnt -sich: Zukünftige Kernel haben die Unterstützung für ihr Produkt schon -eingebaut, Versionskonflikte oder das mühsame Kernel-Patchen entfällt. +entsprechend dem Kernel-Coding-Style und z\"ogern sie nicht, auf der +Linux-Kernel-Mailingliste um die Aufnahme desselben zu bitten. Die M\"uhe lohnt +sich: Zuk\"unftige Kernel haben die Unterst\"utzung f\"ur ihr Produkt schon +eingebaut, Versionskonflikte oder das m\"uhsame Kernel-Patchen entf\"allt. \subsubsection{Los geht's...} Wie sieht nun ein UIO-Treiber konkret aus? Betrachten wir dazu einen Treiber -für eine PCI-Karte. Die folgenden Beispiele sind Auszüge aus dem bereits -erwähnten Treiber für die Hilscher CIF Feldbuskarte. Er befindet sich seit +f\"ur eine PCI-Karte. Die folgenden Beispiele sind Ausz\"uge aus dem bereits +erw\"ahnten Treiber f\"ur die Hilscher CIF Feldbuskarte. Er befindet sich seit 2.6.23-rc1 im Mainline-Kernel. -Der Treiber unterscheidet sich zunächst nur wenig von einem normalen +Der Treiber unterscheidet sich zun\"achst nur wenig von einem normalen PCI-Kartentreiber. Anhand einer Tabelle mit PCI-ID-Nummern wird dem -PCI-Subsystem mitgeteilt, für welche Karten sich der Treiber zuständig fühlt. -Wird beim Booten eine solche Karte gefunden, so lädt das PCI-Subsystem den +PCI-Subsystem mitgeteilt, f\"ur welche Karten sich der Treiber zust\"andig f\"uhlt. +Wird beim Booten eine solche Karte gefunden, so l\"adt das PCI-Subsystem den Treiber und ruft dessen probe-Funktion auf. Diese muss Karte und -Treiber-Variablen initialisieren und das Ergebnis dieser Bemühungen -zurückmelden. Konnten Treiber und Karte erfolgreich initialisiert werden, so -haben sie dem System ein betriebsbereites PCI-Device hinzugefügt. +Treiber-Variablen initialisieren und das Ergebnis dieser Bem\"uhungen +zur\"uckmelden. Konnten Treiber und Karte erfolgreich initialisiert werden, so +haben sie dem System ein betriebsbereites PCI-Device hinzugef\"ugt. Bei einem UIO-Treiber besteht ihre Hauptarbeit darin, eine Struktur vom Typ -\cmd{struct uio\_info} zu erzeugen und auszufüllen. Beginnen wir mit Name und -Version ihres Treibers. Dies sind beliebige strings, die später über -sysfs-Dateien abgefragt werden können: +\cmd{struct uio\_info} zu erzeugen und auszuf\"ullen. Beginnen wir mit Name und +Version ihres Treibers. Dies sind beliebige strings, die sp\"ater \"uber +sysfs-Dateien abgefragt werden k\"onnen: \begin{lstlisting} /* Struktur anlegen */ @@ -365,33 +365,33 @@ info->name = "Meine UIO Karte"; info->version = "0.0.1"; \end{lstlisting} -Als Nächstes kann der von der Karte verwendete Interrupt eingetragen werden. -Freundlicherweise übergibt der Kernel der probe-Funktion einen Pointer +Als N\"achstes kann der von der Karte verwendete Interrupt eingetragen werden. +Freundlicherweise \"ubergibt der Kernel der probe-Funktion einen Pointer (hier \emph{dev} genannt) auf eine Struktur vom Typ \cmd{struct pci\_dev}, in der derartige Angaben schon vom PCI-Subsystem eingetragen wurden. Unsere Aufgabe -ist also leicht zu erfüllen: +ist also leicht zu erf\"ullen: \begin{lstlisting} info->irq = dev->irq; \end{lstlisting} Ausserdem kann man dem UIO-Framework mitteilen, dass man einen -"Fast"-Interrupthandler möchte und für Interrupt-Sharing vorbereitet ist: +"Fast"-Interrupthandler m\"ochte und f\"ur Interrupt-Sharing vorbereitet ist: \begin{lstlisting} info->irq_flags = IRQF_DISABLED | IRQF_SHARED; \end{lstlisting} -Die Adresse des (noch zu erstellenden) Interrupt-Handlers darf natürlich +Die Adresse des (noch zu erstellenden) Interrupt-Handlers darf nat\"urlich nicht fehlen: \begin{lstlisting} info->handler = mein_irq_handler; \end{lstlisting} -Jetzt wäre noch der Speicher der PCI-Karte anzugeben. Nehmen wir an, die Karte -habe nur einen solchen Bereich. Wir erfahren Adresse und Größe des Bereichs -wieder mit Hilfe des Pointers \emph{dev}. Zusätzlich geben wir an, dass es sich um +Jetzt w\"are noch der Speicher der PCI-Karte anzugeben. Nehmen wir an, die Karte +habe nur einen solchen Bereich. Wir erfahren Adresse und Gr\"o\ss e des Bereichs +wieder mit Hilfe des Pointers \emph{dev}. Zus\"atzlich geben wir an, dass es sich um physikalischen Speicher handelt: \begin{lstlisting} @@ -400,10 +400,10 @@ info->mem[0].size = pci_resource_len(dev, 0); info->mem[0].memtype = UIO_MEM_PHYS; \end{lstlisting} -Die hier eingetragene physikalische Adresse kann nicht direkt für Zugriffe +Die hier eingetragene physikalische Adresse kann nicht direkt f\"ur Zugriffe verwendet werden. Sie wird vom UIO-Framework beim \cmd{mmap()}-Aufruf in den Userspace gemappt. Allerdings wird man sicherlich auch in der Interrupt-Routine -Zugriff auf den Speicher benötigen. Dazu mappen wir die Adresse in einen vom +Zugriff auf den Speicher ben\"otigen. Dazu mappen wir die Adresse in einen vom Kernel verwendbaren Bereich: \begin{lstlisting} @@ -411,7 +411,7 @@ info->mem[0].internal_addr = ioremap(pci_resource_start(dev, 0), pci_resource_len(dev, 0) ); \end{lstlisting} -Damit haben wir unserer Pflicht Genüge getan und können unser Device beim +Damit haben wir unserer Pflicht Gen\"uge getan und k\"onnen unser Device beim UIO-Framework registrieren: \begin{lstlisting} @@ -419,14 +419,14 @@ uio_register_device(&dev->dev, info); \end{lstlisting} Das war's. Ein neues UIO-Device hat das Licht der Welt erblickt. Es gibt jetzt -eine Gerätedatei \cmd{/dev/uio0} sowie verschiedene Dateien im Verzeichnis +eine Ger\"atedatei \cmd{/dev/uio0} sowie verschiedene Dateien im Verzeichnis \cmd{/sys/class/uio/uio0/}, die die in \cmd{struct uio\_info} enthaltenen Daten -wiedergeben. Natürlich wird man in der Realität dem obigen Beispielcode noch -Fehlerüberprüfungen hinzufügen, dies wurde hier der Übersichtlichkeit halber +wiedergeben. Nat\"urlich wird man in der Realit\"at dem obigen Beispielcode noch +Fehler\"uberpr\"ufungen hinzuf\"ugen, dies wurde hier der \"Ubersichtlichkeit halber weggelassen. -Damit das Ganze funktioniert, muss natürlich noch der oben angegebene -Interrupt-Handler implementiert werden. Sein Gerüst sieht so aus: +Damit das Ganze funktioniert, muss nat\"urlich noch der oben angegebene +Interrupt-Handler implementiert werden. Sein Ger\"ust sieht so aus: \begin{lstlisting} static irqreturn_t mein_irq_handler(int irq, struct uio_info *dev_info) @@ -437,7 +437,7 @@ static irqreturn_t mein_irq_handler(int irq, struct uio_info *dev_info) return IRQ_NONE; \end{lstlisting} - Hier sind Zugriffe mit Hilfe von ioread/iowrite möglich: + Hier sind Zugriffe mit Hilfe von ioread/iowrite m\"oglich: \begin{lstlisting} ein_byte = ioread8(ptr + MEIN_REGISTER_OFFSET); @@ -450,71 +450,71 @@ static irqreturn_t mein_irq_handler(int irq, struct uio_info *dev_info) } \end{lstlisting} -Jetzt ist der Kernel-Teil des Treibers komplett. Beispiele für vollständige +Jetzt ist der Kernel-Teil des Treibers komplett. Beispiele f\"ur vollst\"andige Treiber finden sich im Verzeichnis \cmd{drivers/uio/} in den Kernel-Quellen oder auf dem Server des Open Source Automation Development Lab (www.osadl.org). -Ausführliche Dokumentation findet sich auch in den Kernel-Quellen in +Ausf\"uhrliche Dokumentation findet sich auch in den Kernel-Quellen in \cmd{Documentation/DocBook/uio-howto.tmpl}; mit \cmd{make htmldocs} erstellt man daraus eine lesbare Form. \subsubsection{Testen mit lsuio} -Hat man einen UIO-Kerneltreiber geladen, so führt der erste Weg ins Verzeichnis -\cmd{/sys/class/uio/uio0}, wo man überprüft, ob alle Dateien die erwarteten -Werte enthalten. Dies kann auf Dauer recht lästig sein, besonders, wenn man +Hat man einen UIO-Kerneltreiber geladen, so f\"uhrt der erste Weg ins Verzeichnis +\cmd{/sys/class/uio/uio0}, wo man \"uberpr\"uft, ob alle Dateien die erwarteten +Werte enthalten. Dies kann auf Dauer recht l\"astig sein, besonders, wenn man mehrere UIO-Devices gleichzeitig testen will. Hier hilft ein kleines Tool -namens \cmd{lsuio}, das alle diese Werte übersichtlich auflistet. +namens \cmd{lsuio}, das alle diese Werte \"ubersichtlich auflistet. Der Sourcecode dieses Tools findet sich auf dem Server des OSADL. Nach dem -Auspacken des Archivs erstellt das übliche +Auspacken des Archivs erstellt das \"ubliche \begin{lstlisting} ./configure && make && make install \end{lstlisting} -das Tool. Dabei wird auch eine manpage installiert, die die möglichen Optionen -des Programms erläutert. Zum Beispiel sorgt die Option -m dafür, dass -\cmd{lsuio} testweise überprüft, ob der Speicher der Karte problemlos in den +das Tool. Dabei wird auch eine manpage installiert, die die m\"oglichen Optionen +des Programms erl\"autert. Zum Beispiel sorgt die Option -m daf\"ur, dass +\cmd{lsuio} testweise \"uberpr\"uft, ob der Speicher der Karte problemlos in den Userspace gemappt werden kann. -Der recht übersichtliche Sourcecode von \cmd{lsuio} (er besteht nur aus zwei -C-Dateien) kann im Übrigen als Beispiel für eigene Anwendungen dienen. Der -Userspace-Teil des Treibers sollte nämlich nie eine bestimmte Version des -Kerneltreibers voraussetzen. Ebenso sollte er nicht als selbstverständlich +Der recht \"ubersichtliche Sourcecode von \cmd{lsuio} (er besteht nur aus zwei +C-Dateien) kann im \"Ubrigen als Beispiel f\"ur eigene Anwendungen dienen. Der +Userspace-Teil des Treibers sollte n\"amlich nie eine bestimmte Version des +Kerneltreibers voraussetzen. Ebenso sollte er nicht als selbstverst\"andlich voraussetzen, dass das eigene Device immer als \cmd{/dev/uio0} erscheint. -Durch Überprüfen der Dateien \cmd{name} und \cmd{version} in den Verzeichnissen +Durch \"Uberpr\"ufen der Dateien \cmd{name} und \cmd{version} in den Verzeichnissen unterhalb von \cmd{/sys/class/uio} kann man diese Informationen auf sichere Weise gewinnen. \subsubsection{Weiter geht's im Userspace} -Der Userspace-Teil des Treibers wird zunächst über das sysfs den Namen des -zuständigen Device-Files ermitteln. Im Folgenden wird der Einfachkeit halber -\cmd{/dev/uio0} angenommen. Ausserdem wird er überprüfen, ob die Version des -Kerneltreibers den Erwartungen entspricht. Wenn Alles im grünen Bereich ist, -wird \cmd{/dev/uio0} geöffnet: +Der Userspace-Teil des Treibers wird zun\"achst \"uber das sysfs den Namen des +zust\"andigen Device-Files ermitteln. Im Folgenden wird der Einfachkeit halber +\cmd{/dev/uio0} angenommen. Ausserdem wird er \"uberpr\"ufen, ob die Version des +Kerneltreibers den Erwartungen entspricht. Wenn Alles im gr\"unen Bereich ist, +wird \cmd{/dev/uio0} ge\"offnet: \begin{lstlisting} int fd = open("/dev/uio0", O_RDWR); \end{lstlisting} -Jetzt müssen wir uns Zugriff auf den Speicher der Karte verschaffen. Nehmen -wir an, die Karte verfügt über einen 4kByte großen Bereich, auf den wir +Jetzt m\"ussen wir uns Zugriff auf den Speicher der Karte verschaffen. Nehmen +wir an, die Karte verf\"ugt \"uber einen 4kByte gro\ss en Bereich, auf den wir zugreifen wollen: \begin{lstlisting} void* map_addr = mmap( NULL, 4096, PROT_READ, MAP_SHARED, fd, 0); \end{lstlisting} -Jetzt enthält \cmd{map\_addr} einen Zeiger, mit dem direkt auf den Speicher +Jetzt enth\"alt \cmd{map\_addr} einen Zeiger, mit dem direkt auf den Speicher der Karte zugegriffen werden kann. Der Treiber wird jetzt die Register der -Karte mit sinnvollen Werten beschreiben. Zuletzt wird er dafür sorgen, dass +Karte mit sinnvollen Werten beschreiben. Zuletzt wird er daf\"ur sorgen, dass die Karte Interrupts generiert. Auf das Eintreffen von Interrupts wartet der Treiber, indem er in einer -Schleife einen blockierenden \cmd{read()}-Aufruf für das Device-File ausführt. +Schleife einen blockierenden \cmd{read()}-Aufruf f\"ur das Device-File ausf\"uhrt. Dabei liest er einen vorzeichenbehafteten 32-bit-Wert. Da \cmd{read()} -standardmäßig blockiert, wenn bei \cmd{open()} kein \cmd{O\_NONBLOCK} +standardm\"a\ss ig blockiert, wenn bei \cmd{open()} kein \cmd{O\_NONBLOCK} angegeben wurde, sieht das einfach so aus: \begin{lstlisting} @@ -527,11 +527,11 @@ while (read(fd, &irq_count, 4)==4) { } \end{lstlisting} -Natürlich sollte die Schleife noch eine Abbruchbedingung haben, damit das +Nat\"urlich sollte die Schleife noch eine Abbruchbedingung haben, damit das Programm irgendwann einmal beendet werden kann. Der in \cmd{irq\_count} gelieferte Wert ist die Gesamtzahl der aufgetretenen Interrupts. Meist wird -man sich diesen Wert merken wollen, damit man beim nächsten Interrupt -überprüfen kann, ob der Wert genau um eins größer geworden ist. +man sich diesen Wert merken wollen, damit man beim n\"achsten Interrupt +\"uberpr\"ufen kann, ob der Wert genau um eins gr\"o\ss er geworden ist. Will man gleichzeitig auf mehrere Filedeskriptoren warten, z.B. auf Interrupts des UIO-Device und auf das Eintreffen von Bytes in einem @@ -539,58 +539,58 @@ Netzwerk-Socket, so kann man auch \cmd{select()} verwenden. Insgesamt ist der Userspace-Teil des Treibers sehr Entwickler-freundlich. Unter der Annahme, dass man die Karte nicht kaputt programmieren kann, -steht Experimenten kaum etwas im Weg. Sie können jedenfalls keine -schlimmeren Abstürze verursachen als beim Programmieren jeder anderen +steht Experimenten kaum etwas im Weg. Sie k\"onnen jedenfalls keine +schlimmeren Abst\"urze verursachen als beim Programmieren jeder anderen Anwender-Applikation. \subsubsection{UIO oder nicht UIO} Sollen jetzt in Zukunft alle Treiber mittels UIO realisiert werden? Sicher -nicht. UIO eignet sich sehr gut für Hardware, die Interrupts erzeugt, deren -Register durch Memory-Mapping in den Userspace gebracht werden können, und +nicht. UIO eignet sich sehr gut f\"ur Hardware, die Interrupts erzeugt, deren +Register durch Memory-Mapping in den Userspace gebracht werden k\"onnen, und die vor allem nur wenig mit anderen Subsystemen des Kernels zu tun haben. Letzteres ist leicht einzusehen, da die Interaktion mit anderen Subsystemen -nur innerhalb des Kernel erfolgen kann. Wollte man etwa den Treiber für -einen SATA-Controller mit UIO realisieren, so müßte dieser ja ein gültiges -Block-Device auf die Beine stellen. Hätte man den dazu nötigen Code, der -eng mit anderen Kernel-Teilen zusammenarbeiten würde, fertiggestellt, so -würde man bemerken, dass für den Userspace nicht mehr viel übrig bleibt. +nur innerhalb des Kernel erfolgen kann. Wollte man etwa den Treiber f\"ur +einen SATA-Controller mit UIO realisieren, so m\"u\ss te dieser ja ein g\"ultiges +Block-Device auf die Beine stellen. H\"atte man den dazu n\"otigen Code, der +eng mit anderen Kernel-Teilen zusammenarbeiten w\"urde, fertiggestellt, so +w\"urde man bemerken, dass f\"ur den Userspace nicht mehr viel \"ubrig bleibt. -Auch Hardware, die keine Interrupts erzeugt, ist kein idealer Kandidat für +Auch Hardware, die keine Interrupts erzeugt, ist kein idealer Kandidat f\"ur UIO, da die saubere Handhabung von Interrupts die eigentliche Besonderheit des Frameworks darstellt. Das reine Mapping von Speicher in den Userspace kann man auch ohne UIO haben. Allerdings bietet eine Implementierung mit Hilfe von UIO immer noch den Vorteil, eine standardisierte und dokumentierte sysfs-Schnittstelle gratis dazu zu bekommen. -Eine weitere Einschränkung besteht darin, dass UIO in seiner aktuellen Version -kein DMA unterstützt. Die Entwickler planen, dies in einer zukünftigen Version -nachzureichen, falls sich Anwendungen dafür finden. Ein naheliegendes Beispiel -sind natürlich Treiber für Grafikkarten, allerdings hat sich hier durch die +Eine weitere Einschr\"ankung besteht darin, dass UIO in seiner aktuellen Version +kein DMA unterst\"utzt. Die Entwickler planen, dies in einer zuk\"unftigen Version +nachzureichen, falls sich Anwendungen daf\"ur finden. Ein naheliegendes Beispiel +sind nat\"urlich Treiber f\"ur Grafikkarten, allerdings hat sich hier durch die weite Verbreitung von X.org bereits ein anderer Standard etabliert, der im -Übrigen teilweise ähnliche Ansätze wie UIO aufweist. Aber auch I/O-Karten, -beispielsweise schnelle A/D-Wandler, könnten DMA benötigen. Die Zukunft wird +\"Ubrigen teilweise \"ahnliche Ans\"atze wie UIO aufweist. Aber auch I/O-Karten, +beispielsweise schnelle A/D-Wandler, k\"onnten DMA ben\"otigen. Die Zukunft wird zeigen, ob an dieser Stelle Nachfrage besteht. \subsubsection{Fazit} -Durch das seit Kernel-Version 2.6.23 in Linux verfügbare -Userspace I/O-Framework wird es besonders für Industriebetriebe erheblich -einfacher, Treiber für ihre I/O-Karten zu schreiben und zu warten. Der -Kernel-Teil des Treibers beschränkt sich auf ein absolutes Minimum, und das +Durch das seit Kernel-Version 2.6.23 in Linux verf\"ugbare +Userspace I/O-Framework wird es besonders f\"ur Industriebetriebe erheblich +einfacher, Treiber f\"ur ihre I/O-Karten zu schreiben und zu warten. Der +Kernel-Teil des Treibers beschr\"ankt sich auf ein absolutes Minimum, und das UIO-Framework entkoppelt ihn wirkungsvoll von der Vielzahl an internen -Kernelfunktionen, die herkömmliche Treiber verwenden müssen. Die Entwicklung der -eigentlichen Treiber-Funktionalität erfolgt bequem im Userspace, unter Verwendung -der für die Applikationsentwicklung gewohnten Tools und Bibliotheken. +Kernelfunktionen, die herk\"ommliche Treiber verwenden m\"ussen. Die Entwicklung der +eigentlichen Treiber-Funktionalit\"at erfolgt bequem im Userspace, unter Verwendung +der f\"ur die Applikationsentwicklung gewohnten Tools und Bibliotheken. -Hat man sich einmal für UIO entschieden, so sollte man unbedingt anstreben, den +Hat man sich einmal f\"ur UIO entschieden, so sollte man unbedingt anstreben, den Kernelteil des Treibers im Mainline-Kernel unterzubringen. Auf diese Weise -erspart man sich und seinen Kunden das ständige Patchen des Kernels und die +erspart man sich und seinen Kunden das st\"andige Patchen des Kernels und die Pflege eines out-of-tree Moduls. -Verhilft man seinem Kernel zusätzlich zu Echtzeit-Fähigkeiten, indem man den -Realtime-Preemption-Patch einspielt, so erhält man ein einfach zu -programmierendes und vollständig aus Open Source-Software bestehendes System -für die Automatisierungstechnik. +Verhilft man seinem Kernel zus\"atzlich zu Echtzeit-F\"ahigkeiten, indem man den +Realtime-Preemption-Patch einspielt, so erh\"alt man ein einfach zu +programmierendes und vollst\"andig aus Open Source-Software bestehendes System +f\"ur die Automatisierungstechnik. \input{tailhandout} diff --git a/linux-basics/boot-process/handout_boot-process_de.tex b/linux-basics/boot-process/handout_boot-process_de.tex index 0b36a61..40b62c8 100644 --- a/linux-basics/boot-process/handout_boot-process_de.tex +++ b/linux-basics/boot-process/handout_boot-process_de.tex @@ -4,99 +4,99 @@ \subsubsection{Aufgaben des Bootloaders} -Hauptaufgabe des Bootloaders ist die rudimentäre Initialisierung der +Hauptaufgabe des Bootloaders ist die rudiment"are Initialisierung der Hardware, so dass mindestens das RAM benutzt werden kann. Dazu ist auf den meisten Boards die Initialisierung eines (S)DRAM-Controllers erforderlich. -Soll das Board aus einem NAND-Flash booten können, so muss auch dessen +Soll das Board aus einem NAND-Flash booten k"onnen, so muss auch dessen Controller initialisiert werden. Viele Prozessoren beinhalten PLLs, die aus dem Prozessortakt andere Clocks -für verschiedene Peripherie-Einheiten generieren. Auch diese müssen +f"ur verschiedene Peripherie-Einheiten generieren. Auch diese m"ussen initialisiert werden. -Anschließend müssen die Peripherie-Einheiten initialisiert werden, die -der Bootloader benötigt, um den Kernel laden zu können. Für TFTP-Boot wäre +Anschlie\ss end m"ussen die Peripherie-Einheiten initialisiert werden, die +der Bootloader ben"otigt, um den Kernel laden zu k"onnen. F"ur TFTP-Boot w"are dies beispielsweise der Netzwerk-Chip. -Meist ist es auch erwünscht, dass der Bootloader eine serielle Schnittstelle -initialisiert. Dies ermöglicht nicht nur hilfreiche Meldungen aus dem -Bootloader, es ermöglicht auch dem Kernel bereits im frühen Stadium des +Meist ist es auch erw"unscht, dass der Bootloader eine serielle Schnittstelle +initialisiert. Dies erm"oglicht nicht nur hilfreiche Meldungen aus dem +Bootloader, es erm"oglicht auch dem Kernel bereits im fr"uhen Stadium des Bootvorgangs die Ausgabe von Meldungen (und nicht erst nach dem Laden seines UART-Treibers und der Konsole). Viele Bootloader bieten ausserdem eine Art Monitorprogramm, mit dem man mit Hilfe eines Terminalprogramms interaktiv -Einstellungen ändern oder Speicher lesen und schreiben kann. +Einstellungen "andern oder Speicher lesen und schreiben kann. -Nach erfolgreicher Initialisierung lädt der Bootloader von der gewählten +Nach erfolgreicher Initialisierung l"adt der Bootloader von der gew"ahlten Quelle das komprimierte Kernel-Image ins RAM. Am Anfang eines komprimierten -zImage steht (natürlich unkomprimiert) der Dekompressor-Code. Der Bootloader +zImage steht (nat"urlich unkomprimiert) der Dekompressor-Code. Der Bootloader springt diese Adresse an und hat damit seine Arbeit beendet. Alles weitere -läuft im Kernel ab. +l"auft im Kernel ab. -\subsubsection{Gängige Bootloader} +\subsubsection{G"angige Bootloader} Die Wahl des Bootloaders ist weitgehend eine Geschmacksfrage. Die verbreiteten Bootloader U-Boot und Redboot bieten im Wesentlichen die gleiche -Funktionalität. Die Bedienung unterscheidet sich zwar deutlich, aber der -ohnehin nötige Einarbeitungsaufwand dürfte bei beiden etwa gleich sein. +Funktionalit"at. Die Bedienung unterscheidet sich zwar deutlich, aber der +ohnehin n"otige Einarbeitungsaufwand d"urfte bei beiden etwa gleich sein. Auch beim Kompilieren dieser Bootloader sind die Unterschiede nicht gross. Beide zeichnen sich durch schwer durchschaubaren Sourcecode und ein eigenwilliges Buildsystem aus. -Es gibt aber auch die Möglichkeit, ganz auf einen derartigen Bootloader zu +Es gibt aber auch die M"oglichkeit, ganz auf einen derartigen Bootloader zu verzichten. Statt dessen verwendet man einen minimalen \emph{Initial Program -Loader (IPL)}, der lediglich die rudimentären Initialisierungsaufgaben -erfüllt und danach einen minimalen Bootkernel lädt und ausführt. Dieser -lädt wiederum den eigentlichen Produktiv-Kernel nach. +Loader (IPL)}, der lediglich die rudiment"aren Initialisierungsaufgaben +erf"ullt und danach einen minimalen Bootkernel l"adt und ausf"uhrt. Dieser +l"adt wiederum den eigentlichen Produktiv-Kernel nach. -Vorteile der letztgenannten Vorgehensweise sind hohe Flexibilität und die +Vorteile der letztgenannten Vorgehensweise sind hohe Flexibilit"at und die Tatsache, dass man im Bootkernel schon nach wenigen hundert Millisekunden -jeden gewünschten Treiber zur Verfügung hat. Dadurch können in elegante +jeden gew"unschten Treiber zur Verf"ugung hat. Dadurch k"onnen in elegante Weise Anforderungen wie das Anzeigen eines Bildes auf einem TFT (500 -Millisekunden nach dem Einschalten) gelöst werden. Wollte man dies mit -einem der oben erwähnten Bootloader erreichen, müsste man zunächst die -für das TFT benötigten Treiber vom Kernel in den Bootloader portieren und -dort zum Laufen bringen. Ähnliches gilt für andere gängige Forderungen, +Millisekunden nach dem Einschalten) gel"ost werden. Wollte man dies mit +einem der oben erw"ahnten Bootloader erreichen, m"usste man zun"achst die +f"ur das TFT ben"otigten Treiber vom Kernel in den Bootloader portieren und +dort zum Laufen bringen. "Ahnliches gilt f"ur andere g"angige Forderungen, wie das Booten von einem USB-Stick. -Es erscheint als überflüssige Mühe, einen im Kernel bereits -funktionierenden Treiber in den Bootloader portieren zu müssen. Mit IPL und -Bootkernel sind ausserdem komplexe Aufgaben während des Bootvorgangs, +Es erscheint als "uberfl"ussige M"uhe, einen im Kernel bereits +funktionierenden Treiber in den Bootloader portieren zu m"ussen. Mit IPL und +Bootkernel sind ausserdem komplexe Aufgaben w"ahrend des Bootvorgangs, beispielsweise automatisierte und sichere Firmware-Updates leicht realisierbar. \subsubsection{Bootprobleme: Im Bootloader} -Während der Entwicklungsphase sind Probleme im Bootloader besonders -unangenehm. Falls dieser bereits abstürzt, ehe er die serielle Schnittstelle +W"ahrend der Entwicklungsphase sind Probleme im Bootloader besonders +unangenehm. Falls dieser bereits abst"urzt, ehe er die serielle Schnittstelle initialisieren konnte, so sieht man schlichtweg gar nichts. Aber auch bei -späteren Fehlern ist der Entwicklungszyklus mühsam, da man den Bootloader -meist erst mit einem JTAG-Adapter oder ähnlichen Werkzeugen ins Flash des -Boards befördern muss, bevor man den nächsten Versuch machen kann. Bei -Änderungen am Bootloader-Code ist daher große Sorgfalt geboten. Wenn möglich, -sollte man zu zweit an solchem Code arbeiten und sich ständig gegenseitig +sp"ateren Fehlern ist der Entwicklungszyklus m"uhsam, da man den Bootloader +meist erst mit einem JTAG-Adapter oder "ahnlichen Werkzeugen ins Flash des +Boards bef"ordern muss, bevor man den n"achsten Versuch machen kann. Bei +"Anderungen am Bootloader-Code ist daher gro\ss e Sorgfalt geboten. Wenn m"oglich, +sollte man zu zweit an solchem Code arbeiten und sich st"andig gegenseitig kontrollieren. -Häufige Problemquellen im Bootloader sind beispielsweise: +H"aufige Problemquellen im Bootloader sind beispielsweise: \begin{itemize} \item Der Bootloader wurde nicht korrekt ins Flash geschrieben. In einem Fall passierte dies beispielsweise, wenn der Compiler ein Binary mit - ungerader Länge erzeugte. Aber auch falsche Konfiguration des JTAGer - kann zu solchen Problemen führen. -\item Im Bootloader wurden die Timings für Bus-Schnittstellen wie RAM oder + ungerader L"ange erzeugte. Aber auch falsche Konfiguration des JTAGer + kann zu solchen Problemen f"uhren. +\item Im Bootloader wurden die Timings f"ur Bus-Schnittstellen wie RAM oder Flash nicht korrekt eingestellt. Gerade wenn die Timings nicht ganz falsch, sondern nur grenzwertig sind, kann es zu schwer reproduzierbaren Bootproblemen kommen. -\item Die Ladeadresse für den Kernel ist nicht korrekt. Bei manchen +\item Die Ladeadresse f"ur den Kernel ist nicht korrekt. Bei manchen Bootloadern kann es leicht zu Verwechslungen zwischen physikalischen und virtuellen Adressen kommen. Weder U-Boot noch Redboot melden - einen Fehler, wenn man den Kernel an eine Adresse lädt, an der - sich überhaupt kein RAM befindet... -\item Beim Laden des Kernels per TFTP kann es zusätzlich weitere Probleme - geben, die mit dem Netzwerk zusammenhängen. Diese reichen von falsch - aufgesetzten TFTP-Servern über falsch konfigurierte DHCP-Server oder + einen Fehler, wenn man den Kernel an eine Adresse l"adt, an der + sich "uberhaupt kein RAM befindet... +\item Beim Laden des Kernels per TFTP kann es zus"atzlich weitere Probleme + geben, die mit dem Netzwerk zusammenh"angen. Diese reichen von falsch + aufgesetzten TFTP-Servern "uber falsch konfigurierte DHCP-Server oder falschen IP-Adressen bis hin zu Treiber- oder Hardware-Problemen. \end{itemize} @@ -104,46 +104,46 @@ Häufige Problemquellen im Bootloader sind beispielsweise: Bootprobleme im Kernel sind vergleichsweise einfach zu finden, sobald man eine Konsole auf der seriellen Schnittstelle hat. Der Kernel gibt meist recht -aussagekräftige Fehlermeldungen und bietet viele zusätzliche Debug-Funktionen, +aussagekr"aftige Fehlermeldungen und bietet viele zus"atzliche Debug-Funktionen, die man in der Kernel-Konfiguration aktivieren kann. Falls sich der Kernel -bereits früher aufhängt, so dass man nach der Meldung +bereits fr"uher aufh"angt, so dass man nach der Meldung \cmd{Uncompressing Linux.....} -überhaupt nichts mehr sieht, dann wird es schwieriger. Man sollte zunächst -überprüfen, ob die im Bootloader vorgegebene Commandline für den Kernel -korrekt ist, insbesondere die Einstellung der für die Konsole verwendeten +"uberhaupt nichts mehr sieht, dann wird es schwieriger. Man sollte zun"achst +"uberpr"ufen, ob die im Bootloader vorgegebene Commandline f"ur den Kernel +korrekt ist, insbesondere die Einstellung der f"ur die Konsole verwendeten seriellen Schnittstelle (\cmd{console=tty...}). -Ein weiteres gängiges Problem ist, dass der Kernel am Ende des Bootvorgangs +Ein weiteres g"angiges Problem ist, dass der Kernel am Ende des Bootvorgangs kein Root-Filesystem mounten kann. Dies kann daran liegen, dass man bei der -Kernelkonfiguration vergessen hat, dass \emph{alle} für das Rootfs nötigen -Hardware- und Dateisystem-Treiber in den Kernel einkompiliert sein müssen +Kernelkonfiguration vergessen hat, dass \emph{alle} f"ur das Rootfs n"otigen +Hardware- und Dateisystem-Treiber in den Kernel einkompiliert sein m"ussen und nicht etwa als Module gebaut wurden. Bei Medien, die erst detektiert -werden müssen (z.B. SD-Karten) kann es passieren, dass das Medium noch nicht +werden m"ussen (z.B. SD-Karten) kann es passieren, dass das Medium noch nicht bereit ist, wenn der Kernel es mounten will. In diesem Fall hilft der Parameter \cmd{rootwait}. Falls der Kernel zwar das Rootfs mounten kann, aber danach mit einer -Fehlermeldung hängen bleibt, anstatt \cmd{/sbin/init} zu starten, dann +Fehlermeldung h"angen bleibt, anstatt \cmd{/sbin/init} zu starten, dann liegt dies oft an fehlenden Device-Nodes im Verzeichnis \cmd{/dev}. -Überprüfen Sie dies. +"Uberpr"ufen Sie dies. \subsubsection{Bootprobleme: In den Startskripten} Wenn der Kernel erfolgreich das Rootfs mounten und \cmd{/sbin/init} starten konnte, wird letzteres versuchen, die in \cmd{/etc/inittab} angegebenen -Anweisungen auszuführen. Dies ist normalerweise zunächst der Aufruf eines +Anweisungen auszuf"uhren. Dies ist normalerweise zun"achst der Aufruf eines Startskripts, das in der Regel weitere Skripte und Programme aufruft. Je nach Art der aufgerufenen Programme kann es hier zu weiteren Problemen -kommen. Dazu gehören etwa fehlerhafte Konfigurationsdateien, fehlende -Device-Nodes oder Ähnliches. +kommen. Dazu geh"oren etwa fehlerhafte Konfigurationsdateien, fehlende +Device-Nodes oder "Ahnliches. Ausserdem kommt es bei Startskripten vor, dass diese nicht auf jede Situation sauber und fehlertolerant reagieren. Man sollte vermeiden, dass sich das -Skript zur Konfiguration des Netzwerks aufhängt, wenn kein DHCP-Server +Skript zur Konfiguration des Netzwerks aufh"angt, wenn kein DHCP-Server gefunden wurde oder kein Netzwerkkabel eingesteckt ist. Des weiteren sollte -das Skript selber erkennen, wenn über die Netzwerkschnittstelle das Rootfs +das Skript selber erkennen, wenn "uber die Netzwerkschnittstelle das Rootfs per NFS gemountet wurde, und dann eine Neukonfiguration tunlichst unterlassen. \input{tailhandout} diff --git a/linux-basics/what-is-linux/handout_what-is-linux_de.tex b/linux-basics/what-is-linux/handout_what-is-linux_de.tex index 2ae9b03..c793fe6 100644 --- a/linux-basics/what-is-linux/handout_what-is-linux_de.tex +++ b/linux-basics/what-is-linux/handout_what-is-linux_de.tex @@ -4,8 +4,8 @@ \subsubsection{Geschichtlicher Hintergrund} -Frühe elektronische Rechner, wie der in Abbildung \ref{img:eniac} gezeigte -ENIAC, waren nicht frei programmierbar. Sie wurden für einen bestimmten +Fr\"uhe elektronische Rechner, wie der in Abbildung \ref{img:eniac} gezeigte +ENIAC, waren nicht frei programmierbar. Sie wurden f\"ur einen bestimmten Zweck gebaut, der ENIAC beispielsweise zur Berechnung von ballistischen Flugbahnen. @@ -21,14 +21,14 @@ weiter, was vor allem durch die Erfindung des Transistors beschleunigt wurde. Mit der freien Programmierbarkeit kam gleichzeitig die Nachfrage nach einem Betriebssystem. Zum einen stellte man schnell fest, das bestimmte Operationen, etwa Ein- und Ausgabe-Funktionen, von nahezu jedem Programm immer wieder -benötigt wurden. Zum anderen hatte man bald den Wunsch nach größerer -Hardware-Unabhängigkeit, damit ein einmal geschriebenes Programm ohne große -Änderungen auf verschiedenen Rechnern laufen konnte. +ben\"otigt wurden. Zum anderen hatte man bald den Wunsch nach gr\"o \ss erer +Hardware-Unabh\"angigkeit, damit ein einmal geschriebenes Programm ohne gro\ss e +\"Anderungen auf verschiedenen Rechnern laufen konnte. -Die ersten Ansätze für ein universelles Betriebssystem blieben mehr oder +Die ersten Ans\"atze f\"ur ein universelles Betriebssystem blieben mehr oder weniger erfolglos. Die Entwickler verzettelten sich mit immer neuen Anforderungen und wenig durchdachten Konzepten. Die Systeme wurden -unüberschaubar und für viele der damaligen Rechner zu gross. +un\"uberschaubar und f\"ur viele der damaligen Rechner zu gross. Erst das ab 1969 von Ken Thompson und Dennis Ritchie (Abbildung \ref{img:ken_ritchie}) entwickelte \emph{Unix} konnte sich auf @@ -41,10 +41,10 @@ breiter Ebene durchsetzen und zu einem Standard entwickeln. \label{img:ken_ritchie} \end{figure} -In der zweiten Hälfte der 70-er Jahre veränderte sich der Computer-Markt -radikal. Die Erfindung der integrierten Schaltung ermöglichte es, kleine und -auch für Normalbürger erschwingliche Computer zu bauen. Dadurch entwickelte -sich der bisher auf Hochschulen, Behörden und Großbetriebe beschränkte Markt +In der zweiten H\"alfte der 70-er Jahre ver\"anderte sich der Computer-Markt +radikal. Die Erfindung der integrierten Schaltung erm\"oglichte es, kleine und +auch f\"ur Normalb\"urger erschwingliche Computer zu bauen. Dadurch entwickelte +sich der bisher auf Hochschulen, Beh\"orden und Gro\ss betriebe beschr\"ankte Markt zum Massenmarkt. \begin{figure}[h] @@ -55,114 +55,114 @@ zum Massenmarkt. \end{figure} Als etwas ausgereiftere Homecomputer wie der Apple 2 (Abbildung \ref{img:apple2}) -zunehmend auch in Betrieben als Ergänzung zu den vorhandenen Großrechnern, +zunehmend auch in Betrieben als Erg\"anzung zu den vorhandenen Gro\ss rechnern, beispielsweise als `intelligente' Terminals, eingesetzt wurden, beschloss -IBM, Marktführer bei Großrechnern, dem etwas entgegen zu setzen. Man +IBM, Marktf\"uhrer bei Gro\ss rechnern, dem etwas entgegen zu setzen. Man entwickelte den IBM-PC, der 1981 erschien. Durch die sehr knappen -Zeitvorgaben war es den Entwicklern nur möglich, bereits am Markt befindliche +Zeitvorgaben war es den Entwicklern nur m\"oglich, bereits am Markt befindliche Standard-Chips einzusetzen. Dadurch gelang es Firmen wie Compaq in kurzer Zeit, selbst ``IBM-kompatible'' Rechner auf den Markt zu werfen. Auch auf Unix hatte diese Entwicklung Einfluss. Bis dahin war Unix im -universitären Umfeld entwickelt worden. Die Rechte am Code besaß zwar AT+T, +universit\"aren Umfeld entwickelt worden. Die Rechte am Code besa\ss zwar AT+T, er wurde aber ohne weiteres kostenlos an Dritte weitergegeben, vor allem -zu Ausbildungszwecken. Es gab ja fast niemanden, der einen Unix-fähigen -Computer besaß. Mit dem beginnenden Massenmarkt sah AT+T die Chance, mit +zu Ausbildungszwecken. Es gab ja fast niemanden, der einen Unix-f\"ahigen +Computer besa\ss . Mit dem beginnenden Massenmarkt sah AT+T die Chance, mit Lizenzen Geld zu verdienen, und machte Unix zu Closed Source. Auch zu -Ausbildungszwecken war der Code nicht mehr verfügbar. +Ausbildungszwecken war der Code nicht mehr verf\"ugbar. -Durch diese Lizenzänderung war es vielen Unix-Programmierern nicht mehr +Durch diese Lizenz\"anderung war es vielen Unix-Programmierern nicht mehr gestattet, ihre eigenen Programme zu nutzen. Einer von ihnen, Richard -Stallman, gründete daraufhin 1984 die \emph{Free Software Foundation} und -begann, ein eigenes Unix namens \emph{GNU} völlig neu zu schreiben. Um -die eben gemachten Erfahrungen reicher, entwickelte er für den Code eine +Stallman, gr\"undete daraufhin 1984 die \emph{Free Software Foundation} und +begann, ein eigenes Unix namens \emph{GNU} v\"ollig neu zu schreiben. Um +die eben gemachten Erfahrungen reicher, entwickelte er f\"ur den Code eine eigene Lizenz, die \emph{GNU Public License (GPL)}. Sie stellt sicher, dass -bei Weitergabe eines Programms der Empfänger immer auch ein Recht auf den +bei Weitergabe eines Programms der Empf\"anger immer auch ein Recht auf den Sourcecode hat. Dem GNU-Projekt schlossen sich schnell weitere Programmierer an, und es gelang ihnen in relativ kurzer Zeit, die Grundlagen eines Unix-Systems zu -erstellen. Dazu gehörten neben den vielen kleinen Unix-Systemprogrammen vor +erstellen. Dazu geh\"orten neben den vielen kleinen Unix-Systemprogrammen vor allem auch der Compiler gcc und der Editor Emacs. Beim Kernel war man weniger -glücklich: Man entschied sich für ein zwar theoretisch interessantes, aber in +gl\"ucklich: Man entschied sich f\"ur ein zwar theoretisch interessantes, aber in der Praxis schlecht handhabbares Microkernel-Konzept. Dieser Kernel (\emph{GNU Hurd}) ist bis heute nicht produktiv einsetzbar... 1991 hatte der finnische Student Linus Torvalds einen Terminal-Emulator geschrieben, mit dem er von daheim per Modem auf den Unix-Rechner der -Universität zugreifen konnte. Als er immer mehr Funktionen hinzufügte, etwa +Universit\"at zugreifen konnte. Als er immer mehr Funktionen hinzuf\"ugte, etwa einen Treiber zum Direktzugriff auf seine Harddisk, bemerkte er, dass er eigentlich auch gleich einen Betriebssystem-Kernel schreiben konnte. Er beschaffte sich die POSIX-Spezifikation, in der die Schnittstellen eines Unix-Kernels beschrieben sind, und implementierte eine Funktion nach der anderen. -Nachdem dieser Kernel unter dem Namen \emph{Linux} veröffentlicht war, +Nachdem dieser Kernel unter dem Namen \emph{Linux} ver\"offentlicht war, schlossen sich ebenfalls schnell hunderte von Programmierern an und arbeiteten an der Weiterentwicklung mit. Durch Kombination des -GNU-Betriebssystems mit dem Linux-Kernel entstand so ein vollständig aus +GNU-Betriebssystems mit dem Linux-Kernel entstand so ein vollst\"andig aus freier Software bestehendes System. Der Begriff ``Linux'' bezeichnet also streng genommen nur den Kernel. -Allerdings hat es sich mittlerweile im Sprachgebrauch eingebürgert, das +Allerdings hat es sich mittlerweile im Sprachgebrauch eingeb\"urgert, das komplette System aus Programmen und Kernel als ``Linux'' zu bezeichnen. -\subsubsection{Ein Betriebssystem für Großrechner} +\subsubsection{Ein Betriebssystem f\"ur Gro\ss rechner} -Unix war von Anfang an ein Betriebssystem, das für den Betrieb auf -Großrechnern ausgelegt ist. Das verwundert nicht weiter, den zur Zeit +Unix war von Anfang an ein Betriebssystem, das f\"ur den Betrieb auf +Gro\ss rechnern ausgelegt ist. Das verwundert nicht weiter, den zur Zeit seiner Entstehung gab es noch keine Einzelplatzrechner im Sinne des heutigen PC. Die mit dieser Anwendung verbundenen Design-Entscheidungen -sind auch heute noch wirksam und bestimmen maßgeblich das Verhalten von +sind auch heute noch wirksam und bestimmen ma\ss geblich das Verhalten von Linux-Systemen. -Durch die freie Verfügbarkeit von Linux gab und gibt es ausserdem zahlreiche +Durch die freie Verf\"ugbarkeit von Linux gab und gibt es ausserdem zahlreiche Anwender mit ganz unterschiedlichen Anforderungen. Von Cluster-basierten Datenbankservern bis zu kleinen batteriebetriebenen PDAs ist alles vertreten. -Des weiteren werden sehr viele verschiedene Prozessor-Familien unterstützt. -Dadurch war der Kernel schon sehr früh 64-Bit- und Endian-fest. +Des weiteren werden sehr viele verschiedene Prozessor-Familien unterst\"utzt. +Dadurch war der Kernel schon sehr fr\"uh 64-Bit- und Endian-fest. Diesem historischen Hintergrund ist es zu verdanken, dass der Linux-Kernel heute sehr gut mit verschiedensten Hardware-Eigenschaften skaliert. Aus dem -selben Source-Code kann ein Kernel für einen Server mit 1024 CPU-Kernen -oder ein Kernel für ein kleines Embedded-System konfiguriert und erzeugt +selben Source-Code kann ein Kernel f\"ur einen Server mit 1024 CPU-Kernen +oder ein Kernel f\"ur ein kleines Embedded-System konfiguriert und erzeugt werden. \subsubsection{Multiuser-Betrieb} Eine weitere wichtige Eigenschaft von Linux, die sich aus der -Großrechner-Tradition ergibt, ist die Multitasking- und Multiuser-Fähigkeit. -Während Multitasking, also das quasi-gleichzeitige Ausführen mehrerer -Programme, heute jedem Computer-Anwender als Selbstverständlichkeit gilt, -verdient der Multiuser-Betrieb nähere Betrachtung. +Gro\ss rechner-Tradition ergibt, ist die Multitasking- und Multiuser-F\"ahigkeit. +W\"ahrend Multitasking, also das quasi-gleichzeitige Ausf\"uhren mehrerer +Programme, heute jedem Computer-Anwender als Selbstverst\"andlichkeit gilt, +verdient der Multiuser-Betrieb n\"ahere Betrachtung. Multiuser-Betrieb bedeutet, dass mehrere Anwender \emph{gleichzeitig} mit dem -System arbeiten können. Jeder Anwender hat dabei den Eindruck, dass ihm das -System allein gehört. Das Betriebssystem muss dazu Funktionalität -bereitstellen, um die Datensicherheit zu gewährleisten und die gerechte -Verteilung der Ressourcen unter den Benutzern sicherzustellen. Dazu gehört +System arbeiten k\"onnen. Jeder Anwender hat dabei den Eindruck, dass ihm das +System allein geh\"ort. Das Betriebssystem muss dazu Funktionalit\"at +bereitstellen, um die Datensicherheit zu gew\"ahrleisten und die gerechte +Verteilung der Ressourcen unter den Benutzern sicherzustellen. Dazu geh\"ort unter anderem, dass alle Dateien und Verzeichnisse mit Benutzerkennungen -versehen werden, die jedem Benutzer sinnvolles Arbeiten ermöglichen, aber -gleichzeitig seinen Zugriff auf fremde Daten einschränken. Diese -Einschränkungen müssen im Kernel realisiert werden, damit sie nicht auf -Anwenderebene umgangen werden können. +versehen werden, die jedem Benutzer sinnvolles Arbeiten erm\"oglichen, aber +gleichzeitig seinen Zugriff auf fremde Daten einschr\"anken. Diese +Einschr\"ankungen m\"ussen im Kernel realisiert werden, damit sie nicht auf +Anwenderebene umgangen werden k\"onnen. -In Unix war diese Funktionalität per Design schon immer vorhanden, während +In Unix war diese Funktionalit\"at per Design schon immer vorhanden, w\"ahrend aus der Tradition der Einzelplatz-Rechner entstandene Betriebssysteme wie DOS -oder Windows dies bis heute nicht leisten. Natürlich ist die freie Lizenz -von Linux hier ebenfalls von Vorteil. Proprietäre Betriebssysteme haben -schon aus Lizenzgründen ein Problem damit, wenn mehrere Anwender einen -Rechner nutzen können. +oder Windows dies bis heute nicht leisten. Nat\"urlich ist die freie Lizenz +von Linux hier ebenfalls von Vorteil. Propriet\"are Betriebssysteme haben +schon aus Lizenzgr\"unden ein Problem damit, wenn mehrere Anwender einen +Rechner nutzen k\"onnen. \subsubsection{Login} -Beim Hochfahren eines Linux-Systems werden üblicherweise alle für den +Beim Hochfahren eines Linux-Systems werden \"ublicherweise alle f\"ur den Systemstart vorgesehenen Programme automatisch gestartet, ohne dass dazu -ein Benutzereingriff nötig wäre. Durch Anpassung der dafür verantwortlichen +ein Benutzereingriff n\"otig w\"are. Durch Anpassung der daf\"ur verantwortlichen Startskripte kann man so auch seine eigenen Applikationen starten. An dieser Stelle hat man root-Rechte, also vollen Zugriff auf alle Ressourcen. -Möchte nach dem Hochfahren ein Benutzer mit dem System arbeiten, so muss +M\"ochte nach dem Hochfahren ein Benutzer mit dem System arbeiten, so muss er dem System mitteilen, wer er ist, und dies gegebenenfalls durch einen Authentifizierungsprozess glaubhaft machen. Diesen Vorgang nennt man ``Login''. @@ -170,34 +170,34 @@ Authentifizierungsprozess glaubhaft machen. Diesen Vorgang nennt man \begin{figure}[h] \centering \includegraphics[width=0.3\textwidth]{images/CPU_und_Terminals1-600px.png} -\caption{Schematische Darstellung eines Großrechners} +\caption{Schematische Darstellung eines Gro\ss rechners} \label{img:mainframe} \end{figure} Abbildung \ref{img:mainframe} zeigt die Situation in schematischer Weise. Am -Großrechner sind mehrere Terminals angeschlossen. Früher waren dies +Gro\ss rechner sind mehrere Terminals angeschlossen. Fr\"uher waren dies Fernschreiber, daher die Bezeichnung tty (von engl. teletype). Auf Abbildung \ref{img:ken_ritchie} kann man dies sehen -- da gab es noch keine Monitore. Unter Linux sind dies sogenannte \emph{virtuelle Terminals}. Selbst auf einem Laptop, der an nichts anderes angeschlossen ist, hat man mehrere solcher -virtueller Terminals zur Verfügung. Eines davon wird meist von der grafischen -Oberfläche benutzt. +virtueller Terminals zur Verf\"ugung. Eines davon wird meist von der grafischen +Oberfl\"ache benutzt. -Zusätzlich gibt es weitere physikalische Terminals, so haben beispielsweise +Zus\"atzlich gibt es weitere physikalische Terminals, so haben beispielsweise serielle Schnittstellen Bezeichnungen wie ttyS0, ttyS1 und so weiter. Jedes -dieser Terminals ist völlig autark, das heisst, man muss sich in jedem +dieser Terminals ist v\"ollig autark, das heisst, man muss sich in jedem Terminal erneut einloggen und authentifizieren. -Logins sind unter Linux auf mehreren Wegen möglich. Ausser dem von Desktops +Logins sind unter Linux auf mehreren Wegen m\"oglich. Ausser dem von Desktops her gewohnten Login am Bildschirm kann man sich auch mit Hilfe eines -Terminal-Programms über eine serielle Schnittstelle einloggen. Weit verbreitet -sind auch Logins über Netzwerkprotokolle wie ssh oder telnet. +Terminal-Programms \"uber eine serielle Schnittstelle einloggen. Weit verbreitet +sind auch Logins \"uber Netzwerkprotokolle wie ssh oder telnet. -Da diese Login-Möglichkeiten unter Windows nicht üblich sind, kommt es hier -häufig zu Verständnisschwierigkeiten. Als Übung sollten Sie sich per ssh +Da diese Login-M\"oglichkeiten unter Windows nicht \"ublich sind, kommt es hier +h\"aufig zu Verst\"andnisschwierigkeiten. Als \"Ubung sollten Sie sich per ssh auf einem entfernten Rechner einloggen und dann ein Programm starten. Machen -Sie sich klar, dass das Programm auf dem entfernten Rechner ausgeführt wird +Sie sich klar, dass das Programm auf dem entfernten Rechner ausgef\"uhrt wird und nicht etwa auf dem Rechner, an dem Sie gerade sitzen. \newpage @@ -207,7 +207,7 @@ und nicht etwa auf dem Rechner, an dem Sie gerade sitzen. \begin{enumerate} \item Wie alt ist das Unix-Konzept mittlerweile? \item Seit wann gibt es den Linux-Kernel? -\item Warum ist die Großrechner-Tradition von Linux auch für Embedded Systems +\item Warum ist die Gro\ss rechner-Tradition von Linux auch f\"ur Embedded Systems von Vorteil? \item Was passiert beim Login-Vorgang? \end{enumerate} diff --git a/realtime/rt-basics/handout_rt-basics_de.tex b/realtime/rt-basics/handout_rt-basics_de.tex index dd775b6..8580797 100644 --- a/realtime/rt-basics/handout_rt-basics_de.tex +++ b/realtime/rt-basics/handout_rt-basics_de.tex @@ -5,13 +5,13 @@ \subsubsection{Grundlagen} \paragraph{Was ist Echtzeit?} -Vor der Betrachtung verschiedener Ansätze, Linux echtzeitfähig zu machen, ist es -notwendig, einige grundlegende Begrifflichkeiten zur erläutern: +Vor der Betrachtung verschiedener Ans\"atze, Linux echtzeitf\"ahig zu machen, ist es +notwendig, einige grundlegende Begrifflichkeiten zur erl\"autern: \begin{itemize} \item Echtzeit: Zur Definition eines Echtzeitsystems kann man folgende Aussagen Treffen: Auf -einem Echtzeitsystem hängt die Korrektheit einer Berechnung nicht nur von ihrer -logischen Korrektheit, sondern auch von der Ausführung zum korrekten Zeitpunkt +einem Echtzeitsystem h\"angt die Korrektheit einer Berechnung nicht nur von ihrer +logischen Korrektheit, sondern auch von der Ausf\"uhrung zum korrekten Zeitpunkt ab. Das Nichteinhalten eines bestimmten Zeitrahmens resultiert in einem Fehler. \item Latenzzeit: Unter Latenzzeit versteht man den Zeitraum zwischen dem Auftreten eines Events und der Reaktion auf dieses Event. @@ -19,47 +19,47 @@ Auftreten eines Events und der Reaktion auf dieses Event. \end{itemize} \paragraph{Anwendungsbereiche} -Die wohl gängigsten Anwendungsbereiche für Echtzeitsysteme sind die +Die wohl g\"angigsten Anwendungsbereiche f\"ur Echtzeitsysteme sind die Steuerungs- und Automatisierungstechnik, Multimediasysteme und die Luft- und Raumfahrttechnik. Ein weiteres interessantes Einsatzgebiet stellt die Finanzdienstleistung dar. Hier geht es insbesondere um die zeitgenaue, -zuverlässige Abwicklung von Finanztransaktionen über hochverteilte Systeme. +zuverl\"assige Abwicklung von Finanztransaktionen \"uber hochverteilte Systeme. \paragraph{Anforderungen an ein Echtzeitsystem} -Ein Echtzeitsystem muß in der Lage sein, in einem garantierten Zeitrahmen auf -ein Ereignis zu reagieren. Es muß also möglich sein, in möglichst kurzer Zeit +Ein Echtzeitsystem mu\ss in der Lage sein, in einem garantierten Zeitrahmen auf +ein Ereignis zu reagieren. Es mu\ss also m\"oglich sein, in m\"oglichst kurzer Zeit von einer niederprioren Task auf eine hochpriore Task umzuschalten, falls diese -Rechenzeit benötigt. Das System muß also möglichst ''feingranular'' +Rechenzeit ben\"otigt. Das System mu\ss also m\"oglichst ''feingranular'' unterbrechbar sein. Doch allein die Unterbrechbarkeit kann kein deterministisches Zeitverhalten garantieren. So kann eine niederpriore Task Resourcen blockieren, die von einer -hochprioren Task benötigt werden. Wird die niederpriore Task nun unterbrochen, -kommt es zur ''Prioritätsinversion / priority inversion'', da die hochpriore Task +hochprioren Task ben\"otigt werden. Wird die niederpriore Task nun unterbrochen, +kommt es zur ''Priorit\"atsinversion / priority inversion'', da die hochpriore Task auf die Freigabe der Resource wartet, diese aber erst wieder dann freigegeben wird, wenn die niederpriore Task wieder Rechenzeit bekommt. -Gelöst werden kann dieses Problem durch ''prioriy inheritance'' und ''priority ceiling''. +Gel\"ost werden kann dieses Problem durch ''prioriy inheritance'' und ''priority ceiling''. \begin{itemize} -\item Prioritätsvererbung / priority inheritance: Hier wird die Priorität der -niederprioren Task angehoben, um zu erreichen, daß die blockierte Resource +\item Priorit\"atsvererbung / priority inheritance: Hier wird die Priorit\"at der +niederprioren Task angehoben, um zu erreichen, da\ss die blockierte Resource freigegeben werden kann. -\item Prioritätsgrenzen / priority ceiling: Hier wird für jede Resource eine -Prioritätsgrenze festgelegt. Jede Task, die die Resource belegt, wird auf die -Prioritätsgrenze der Resource angehoben. +\item Priorit\"atsgrenzen / priority ceiling: Hier wird f\"ur jede Resource eine +Priorit\"atsgrenze festgelegt. Jede Task, die die Resource belegt, wird auf die +Priorit\"atsgrenze der Resource angehoben. \end{itemize} \subsubsection{Realtime Linux Varianten} \paragraph{Historisches zu Echtzeitlinux} -Im Gegensatz zu traditionellen Echtzeitsystem wurde Linux ursprünglich nicht als +Im Gegensatz zu traditionellen Echtzeitsystem wurde Linux urspr\"unglich nicht als solches designt. Als General Purpose Operating System wurde Linux auf Fairness -und Durchsatz optimiert. Linux echtzeitfähig zu machen, bedeutet also, ein -Standardbetriebssystem um Echtzeitfunktionen bzw. entsprechende Sonderfälle zu -erweitern. Mit dieser Tatsache lassen sich die zwei technischen Ansätze für -Realtime Linux erklären. +und Durchsatz optimiert. Linux echtzeitf\"ahig zu machen, bedeutet also, ein +Standardbetriebssystem um Echtzeitfunktionen bzw. entsprechende Sonderf\"alle zu +erweitern. Mit dieser Tatsache lassen sich die zwei technischen Ans\"atze f\"ur +Realtime Linux erkl\"aren. \begin{itemize} -\item Dual Kernel Ansatz: Hier koexistieren ein Echtzeitkernel, der für alle -zeitkritischen Dinge zuständig ist, und ein Standard Linux Kernel. Dieser Ansatz -setzt voraus, daß alle externen Events zuerst vom Echtzeitkernel bearbeitet -werden, bevor Sie an den Linux Kernel weitergereicht werden können. Die +\item Dual Kernel Ansatz: Hier koexistieren ein Echtzeitkernel, der f\"ur alle +zeitkritischen Dinge zust\"andig ist, und ein Standard Linux Kernel. Dieser Ansatz +setzt voraus, da\ss alle externen Events zuerst vom Echtzeitkernel bearbeitet +werden, bevor Sie an den Linux Kernel weitergereicht werden k\"onnen. Die bekanntesten Vertreter dieser Technik sind RTAI und Xenomai. \item In-Kernel Ansatz: Diese Methode macht Linux an sich zu einem Echtzeitsystem. Dieser Ansatz wird mit dem Realtime Preemption Patch verfolgt @@ -69,11 +69,11 @@ Hauptzweig von Linux abgenickt wurde. \paragraph{RTAI} Das Realtime Application Interface (RTAI) ist eine Entwicklung der Technischen -Universität Mailand und entstand unter der Schirmherrschaft von Professor Paolo -Mantegazza. Oberstes Designziel von RTAI ist und war es, die kleinstmöglichen +Universit\"at Mailand und entstand unter der Schirmherrschaft von Professor Paolo +Mantegazza. Oberstes Designziel von RTAI ist und war es, die kleinstm\"oglichen Latenzzeiten auf einer gegebenen Hardwareplattform zu erzielen. Dieses -Designziel bedingt diverse Einschränkungen für RTAI Applikationen. Weiterhin -wird nur eine recht kleine Anzahl an Zielplattormen unterstützt (derzeit x86, +Designziel bedingt diverse Einschr\"ankungen f\"ur RTAI Applikationen. Weiterhin +wird nur eine recht kleine Anzahl an Zielplattormen unterst\"utzt (derzeit x86, x86\_64 und diverse ARM Plattformen). \begin{figure}[h] \centering @@ -85,11 +85,11 @@ RTAI ist ein typischer Vertreter des Dual Kernel Ansatzes. Abbildung \ref{img:rtai} zeigt die Funktionsweise von RTAI. \paragraph{Xenomai} -Das Xenomai Projekt wurde im Jahre 2001 gegründet. Im Gegensatz zu RTAI erlaubt -Xenomai auch Echtzeit im Userpace (RTAI erlaubt dies nur sehr eingeschränkt). +Das Xenomai Projekt wurde im Jahre 2001 gegr\"undet. Im Gegensatz zu RTAI erlaubt +Xenomai auch Echtzeit im Userpace (RTAI erlaubt dies nur sehr eingeschr\"ankt). Die Besonderheit von Xenomai sind die sogenannten Skins, die es vereinfachen sollen, Applikationen von anderen Echtzeitsystemen nach Xenomai zu portieren. -Xenomai Skins bilden die API dieser Systeme ab. Xenomai unterstützt derzeit +Xenomai Skins bilden die API dieser Systeme ab. Xenomai unterst\"utzt derzeit folgende Architekturen: PowerPC32, PowerPC64, x86, x86\_64, Blackfin, ARM und ia64). Die zentralen Begriffe im Designkonzept von Xenomai stellen Xenomai Nucleus, die Interrupt Pipeline (IPIPE), Hardware Abstraction Layer (HAL) und @@ -97,12 +97,12 @@ System Abstraction Layer (SAL) dar. IPIPE kann bildlich als virtueller Interruptkontroller betrachtet werden. Sie organisiert das System in verschiedenen Domains. Interrupts werden von IPIPE entgegengenommen und an die einzelnen Domains verteilt. -Nucleus beeinhaltet die Xenomai Core Funktionalität. Dieser ist zuständig dafür, -alle notwendigen Resourcen bereitzustellen, die Skins benötigen, um die Funktionalität -von RTOSsen nachbilden zu können. Der Hardware Abstraction Layer beinhaltet -den Plattform und CPU abhängigen Code. Alle darüberliegenden Layer (darunter auch Nucleus) +Nucleus beeinhaltet die Xenomai Core Funktionalit\"at. Dieser ist zust\"andig daf\"ur, +alle notwendigen Resourcen bereitzustellen, die Skins ben\"otigen, um die Funktionalit\"at +von RTOSsen nachbilden zu k\"onnen. Der Hardware Abstraction Layer beinhaltet +den Plattform und CPU abh\"angigen Code. Alle dar\"uberliegenden Layer (darunter auch Nucleus) bauen darauf auf. HAL ist kombiniert mit dem System Abstraction Layer. Dieser -soll die darüberliegenden Layer, wie z.B. Nucleus, noch portierbarer machen. +soll die dar\"uberliegenden Layer, wie z.B. Nucleus, noch portierbarer machen. Abbildung \ref{img:xenomai} zeigt das technische Zusammenspiel der Xenomai Komponenten. Abbildung \ref{img:ipipe} zeigt die Funktionsweise von IPIPE. \begin{figure}[h] @@ -119,49 +119,49 @@ Komponenten. Abbildung \ref{img:ipipe} zeigt die Funktionsweise von IPIPE. \end{figure} \paragraph{Preempt RT} -Der Realtime Preemption Patch entstand ursprünglich aus Arbeiten von Ingo Molnar -und Thomas Gleixner. Beide sind bis zum heutigen Zeitpunkt die treibenden Kräfte +Der Realtime Preemption Patch entstand urspr\"unglich aus Arbeiten von Ingo Molnar +und Thomas Gleixner. Beide sind bis zum heutigen Zeitpunkt die treibenden Kr\"afte bei der Entwicklung von Preempt RT. Im Gegensatz zu RTAI und Xenomai macht Preempt RT den Linux Kernel an sich -echtzeitfähig. Dies wird im Besonderen durch folgende Mechanismen erreicht: +echtzeitf\"ahig. Dies wird im Besonderen durch folgende Mechanismen erreicht: \begin{itemize} \item Sleeping Spinlocks: Spinlocks werden durch RT Mutexe ersetzt. Raw -Spinlocks ersetzen die Eigenschaft der ursprünglichen Spinlocks. +Spinlocks ersetzen die Eigenschaft der urspr\"unglichen Spinlocks. \item Threaded Interrupt Handlers: Interrupt Handler laufen per Default nicht im harten Interruptkontext, sondern als Kernelthread. \end{itemize} -Viele Mechanismen, die ursprünglich in Preempt RT entwickelt wurden, haben +Viele Mechanismen, die urspr\"unglich in Preempt RT entwickelt wurden, haben bereits Ihren Weg in den Mainline Linuxzweig gefunden: High Resolution Timer -(Hochauflösende Timer unabhängig vom Scheduler Tick), Priority Inheritance, -generisches Interrupthandling für alle Architekturen und mit 2.6.30 nun auch die +(Hochaufl\"osende Timer unabh\"angig vom Scheduler Tick), Priority Inheritance, +generisches Interrupthandling f\"ur alle Architekturen und mit 2.6.30 nun auch die Threaded Interrupt Handler. Weiterhin hat sich die Linux Entwicklergemeinde bereits 2006 darauf geeinigt, -daß Preempt RT in den Linux Kernel integriert wird. Weiterhin bietet der -Realtime Preemption Patch den großen Vorteil, daß Echtzeitapplikationen als POSIX +da\ss Preempt RT in den Linux Kernel integriert wird. Weiterhin bietet der +Realtime Preemption Patch den gro\ss en Vorteil, da\ss Echtzeitapplikationen als POSIX Realtime Applikationen geschrieben werden. Es wird keine spezielle API -verwendet. Preempt RT Unterstützt eine Vielzahl von Architekturen (PowerPc, x86, +verwendet. Preempt RT Unterst\"utzt eine Vielzahl von Architekturen (PowerPc, x86, x86\_64, MIPS, ARM, ...). \begin{figure}[h] \centering \includegraphics[height=0.5\textwidth]{images/preempt_rt.png} -\caption{Überblick Preempt RT} +\caption{\"Uberblick Preempt RT} \label{img:preempt_rt} \end{figure} Wie Abbildung \ref{img:preempt_rt} zeigt, integriert Preempt RT die -Echtzeitfunktionalität ''nahtlos'' in den Linux Kernel. Auch die Entwickler -anderer Projekte haben die Vorzüge von Preempt RT bereits erkannt. Die Roadmap -für Xenomai 3 sieht Preempt RT Support vor. Dies würde den Einsatz von Xenomai -Skins auf Preempt RT Kerneln ermgöglichen. +Echtzeitfunktionalit\"at ''nahtlos'' in den Linux Kernel. Auch die Entwickler +anderer Projekte haben die Vorz\"uge von Preempt RT bereits erkannt. Die Roadmap +f\"ur Xenomai 3 sieht Preempt RT Support vor. Dies w\"urde den Einsatz von Xenomai +Skins auf Preempt RT Kerneln ermg\"oglichen. \subsubsection{Kontrollfragen} \begin{enumerate} \item Was sind die wichtigsten Anforderungen an ein Echtzeitsystem? -\item Welche beiden Ansätze gibt es, um Linux echtzeitfähig zu machen? -\item Was sind die bekanntesten Vertreter für Echtzeitlinux und welche der oben -beschriebenen Ansätze verfolgen Sie? -\item Wird für das Schreiben einer Echtzeitapplikation mit Preempt RT eine -spezielle API benötigt? +\item Welche beiden Ans\"atze gibt es, um Linux echtzeitf\"ahig zu machen? +\item Was sind die bekanntesten Vertreter f\"ur Echtzeitlinux und welche der oben +beschriebenen Ans\"atze verfolgen Sie? +\item Wird f\"ur das Schreiben einer Echtzeitapplikation mit Preempt RT eine +spezielle API ben\"otigt? \end{enumerate} \input{tailhandout} diff --git a/realtime/rt-specialties/handout_rt-specialties_de.tex b/realtime/rt-specialties/handout_rt-specialties_de.tex index 54771ca..2f19a2b 100644 --- a/realtime/rt-specialties/handout_rt-specialties_de.tex +++ b/realtime/rt-specialties/handout_rt-specialties_de.tex @@ -6,7 +6,7 @@ Preempt RT wird als Patch gegen den Mainline Linux Kernel gepflegt. Unter:\newline http://www.kernel.org/pub/linux/kernel/projects/rt sind die aktuellsten Patche -für Preempt RT zu finden. Im Unterverzeichnis older/ sind ältere Patche +f\"ur Preempt RT zu finden. Im Unterverzeichnis older/ sind \"altere Patche archiviert. Das Vorbereiten eines Kerneltrees mit Preempt RT ist denkbar einfach: \begin{lstlisting} @@ -34,8 +34,8 @@ cd linux-2.6.29.5-rt21 ketchup -f --no-gpg 2.6.29.5-rt21 \end{lstlisting} -\paragraph{Konfigurieren und Übersetzen eines Preempt RT Kernels} -Die Konfiguration und das Übersetzen machen keinen Unterschied zu Linux ohne +\paragraph{Konfigurieren und \"Ubersetzen eines Preempt RT Kernels} +Die Konfiguration und das \"Ubersetzen machen keinen Unterschied zu Linux ohne Preempt RT Patch: \begin{lstlisting} # external build directory @@ -44,7 +44,7 @@ mkdir ../build cp /boot/config-x-x-x ../build/.config make O=../build oldconfig \end{lstlisting} -Für ein Echtzeitsystem müssen verschiedene Kerneloptionen aktiviert werden: +F\"ur ein Echtzeitsystem m\"ussen verschiedene Kerneloptionen aktiviert werden: \begin{lstlisting} make O=../build menuconfig \end{lstlisting} @@ -54,7 +54,7 @@ bzw. ''Processor type and features''. \centering \includegraphics[height=0.5\textwidth]{images/menu_rt_001.png} \end{figure} -Dort müssen folgende Optionen aktiviert werden: +Dort m\"ussen folgende Optionen aktiviert werden: \begin{itemize} \item High Resolution Timer Support \item Preemption Mode (Complete Preemption (Real-Time)) @@ -71,7 +71,7 @@ Dort müssen folgende Optionen aktiviert werden: \centering \includegraphics[height=0.5\textwidth]{images/menu_rt_004.png} \end{figure} -Das Übersetzen des Kernels erfolgt nun wie üblich mit +Das \"Ubersetzen des Kernels erfolgt nun wie \"ublich mit \begin{lstlisting} make O=../build make O=../build modules @@ -87,7 +87,7 @@ Eigenschaften von Echtzeitsystemen. Die RT Tests umfassen folgende Tools: \item cyclictest: High Resolution Timer Testsoftware. \item hwlatdetect: Python Script zur Steuerung des Kernelmoduls zur Erkennung von System Management Interrupts (hwlat\_detector). -\item pi\_stress: Stresstest für Mutexe mit Priority Inheritance Attribut +\item pi\_stress: Stresstest f\"ur Mutexe mit Priority Inheritance Attribut \item signaltest: Benchmark, bei dem Signale zwischen Tasks ausgetauscht werden. \end{itemize} Die Sourcen der RT Tests werden in einem GIT Tree verwaltet. @@ -103,11 +103,11 @@ make \subparagraph{Cyclictest} Cyclictest ist die wohl meistgenutzte Testsoftware auf Preempt RT Systemen. Mit Cyclictest kann eine bestimmte Anzahl von Timertasks mit einem definierten -Interval aufgesetzt werden. Für diese Tasks wird kontinuierlich die Abweichung -zum gewünschten Intervall gemessen und hierfür die Maximale und Durchschnittliche -Abweichung aufgezeichnet. Die wichtigsten Parameter für Cyclictest sind die -Anzahl und die Priorität der gewünschten Timertasks, die Art des zu verwendenden -Timers und das gewünschte Timerintervall: +Interval aufgesetzt werden. F\"ur diese Tasks wird kontinuierlich die Abweichung +zum gew\"unschten Intervall gemessen und hierf\"ur die Maximale und Durchschnittliche +Abweichung aufgezeichnet. Die wichtigsten Parameter f\"ur Cyclictest sind die +Anzahl und die Priorit\"at der gew\"unschten Timertasks, die Art des zu verwendenden +Timers und das gew\"unschte Timerintervall: \begin{lstlisting} # 4 Timertasks (2000 , 2500, 3000, 3500us) # -i options tells us the interval of the first task @@ -125,53 +125,53 @@ T: 2 ( 2123) P:78 I:3000 C: 841 Min: 54 Act: 76 Avg: 82 Max: 136 T: 3 ( 2124) P:77 I:3500 C: 723 Min: 67 Act: 95 Avg: 96 Max: 177 \end{lstlisting} \paragraph{Lastszenarien} -Um eine Aussage über das Echtzeitverhaltens treffen zu können, interessiert in +Um eine Aussage \"uber das Echtzeitverhaltens treffen zu k\"onnen, interessiert in der Hauptsache das Verhalten in Worst-Case Szenarien (hohe CPU Last, hohe Interruptlast). Ein ausgezeichnetes Werkzeug, um CPU Last zu erzeugen, ist -''hackbench''. Hackbench wurde ursprünglich als Schedulerbenchmark entwickelt. +''hackbench''. Hackbench wurde urspr\"unglich als Schedulerbenchmark entwickelt. Es erzeugt eine bestimme Anzahl an Prozessgruppen von Clients und Servern, die -über Sockets miteinander kommunizieren:\newline +\"uber Sockets miteinander kommunizieren:\newline http://people.redhat.com/mingo/cfs-scheduler/tools/hackbench.c -Interruptlast, läßt sich hervorragend mit einem Floodping von einem entfernten -Rechner erzeugen. Ein Floodping schickt eine große Anzahl von ICMP Paketen in +Interruptlast, l\"a\ss t sich hervorragend mit einem Floodping von einem entfernten +Rechner erzeugen. Ein Floodping schickt eine gro\ss e Anzahl von ICMP Paketen in kurzer Zeit. Dies erzeugt eine hohe Anzahl von Netzwerkinterrupts. Um Floodpings -zu generieren muß das Programm ping mit Rootrechten und mit der Option -f -ausgeführt werden. +zu generieren mu\ss das Programm ping mit Rootrechten und mit der Option -f +ausgef\"uhrt werden. \subparagraph{Pitfall} -Ein sehr häufig gemeldetes Phänomen bei Testläufen von Cyclictest mit einem -Floodping als Lastszenario, sind extrem große Ausreißer in der Größenordnung von -50ms. Dies ist auf ein ''Feature'' aktueller Preempt RT Kernel zurückzuführen. +Ein sehr h\"aufig gemeldetes Ph\"anomen bei Testl\"aufen von Cyclictest mit einem +Floodping als Lastszenario, sind extrem gro\ss e Ausrei\ss er in der Gr\"o\ss enordnung von +50ms. Dies ist auf ein ''Feature'' aktueller Preempt RT Kernel zur\"uckzuf\"uhren. Da Preempt RT auch auf vielen Desktops eingesetzt wird, auf denen Low Latency -Anwendungen betrieben werden (z.B. Multimedia Anwendungen), häuften sich -Fehlerberichte, die letztendlich nicht auf ein Kernelproblem zurückzuführen +Anwendungen betrieben werden (z.B. Multimedia Anwendungen), h\"auften sich +Fehlerberichte, die letztendlich nicht auf ein Kernelproblem zur\"uckzuf\"uhren waren, sondern auf eine Realtime Applikation, die den Rest des Systems -aushungerte. Daher wurde eine Option eingeführt, die die Laufzeit von Realtime -Tasks beschränken kann. Überschreiten die Realtime Tasks dieses Zeitlimit, -werden diese für einen bestimmten Zeitraum nicht mehr geschedult. Die -Standardeinstellung liegt bei 950ms. Bei Überschreiten der 950ms werden die -Echtzeittasks für 50ms suspendiert. -Da Interrupts unter Preempt RT als Kernelthread mit Echtzeitprioriät laufen +aushungerte. Daher wurde eine Option eingef\"uhrt, die die Laufzeit von Realtime +Tasks beschr\"anken kann. \"Uberschreiten die Realtime Tasks dieses Zeitlimit, +werden diese f\"ur einen bestimmten Zeitraum nicht mehr geschedult. Die +Standardeinstellung liegt bei 950ms. Bei \"Uberschreiten der 950ms werden die +Echtzeittasks f\"ur 50ms suspendiert. +Da Interrupts unter Preempt RT als Kernelthread mit Echtzeitpriori\"at laufen und durch den Floodping eine hohe Anzahl an Netzwerkinterrupts -(einschliesslich der zugehörigen Softinterrupts) erzeugt wird, nehmen Realtime -Tasks im System einen Großteil der Resourcen ein. Somit kann es passieren, daß -dieses Zeitlimit überschritten wird. -Das Limit für die Rechenzeit kann durch Schreiben des gewünschten Wertes nach -/proc/sys/kernel/sched\_rt\_runtime\_us angepaßt werden. -Zum Deaktivieren dieser Funktion muß Folgendes getan werden: +(einschliesslich der zugeh\"origen Softinterrupts) erzeugt wird, nehmen Realtime +Tasks im System einen Gro\ss teil der Resourcen ein. Somit kann es passieren, da\ss +dieses Zeitlimit \"uberschritten wird. +Das Limit f\"ur die Rechenzeit kann durch Schreiben des gew\"unschten Wertes nach +/proc/sys/kernel/sched\_rt\_runtime\_us angepa\ss t werden. +Zum Deaktivieren dieser Funktion mu\ss Folgendes getan werden: \begin{lstlisting} echo -1 > /proc/sys/kernel/sched_rt_runtime_us \end{lstlisting} -\subsubsection{Erstellen einer Realtime Task für Preempt RT} -\paragraph{Schedulingklassen / Prioritäten} +\subsubsection{Erstellen einer Realtime Task f\"ur Preempt RT} +\paragraph{Schedulingklassen / Priorit\"aten} Eine Realtime Applikation auf Preempt RT ist eine POSIX Realtime Applikation. -POSIX sieht für Echtzeitapplikationen folgende Schedulingstrategien vor: +POSIX sieht f\"ur Echtzeitapplikationen folgende Schedulingstrategien vor: \begin{itemize} -\item SCHED\_FIFO: Scheduling mit statischen Prioriäten -\item SCHED\_RR: Round Robin mit Prioritäten +\item SCHED\_FIFO: Scheduling mit statischen Priori\"aten +\item SCHED\_RR: Round Robin mit Priorit\"aten \end{itemize} -Echtzeitpriorität bekommt eine Applikation nur dann, wenn dies explizit -gewünscht wird. Hierzu ist die Funktion sched\_setscheduler() vorgesehen. +Echtzeitpriorit\"at bekommt eine Applikation nur dann, wenn dies explizit +gew\"unscht wird. Hierzu ist die Funktion sched\_setscheduler() vorgesehen. \paragraph{Beispiel einer Echtzeitapplikation} Das folgende Beispiel zeigt eine einfache POSIX Realtimeapplikation: \begin{lstlisting} @@ -223,39 +223,39 @@ int main(int argc, char* argv[]) } } \end{lstlisting} -Die oben aufgelistete Applikation zeigt sehr schön, was notwendig ist, um eine +Die oben aufgelistete Applikation zeigt sehr sch\"on, was notwendig ist, um eine Applikation mit deterministischem Zeitverhalten zu erzeugen: \begin{itemize} -\item RT Scheduling Policy und Priorität festlegen +\item RT Scheduling Policy und Priorit\"at festlegen \item Speicher locken, um undeterministisches Zeitverhalten durch Pagefaults auszuschliessen. -\item ''Stack Pre-Faulting'', um zu vermeiden, daß Stackfaults +\item ''Stack Pre-Faulting'', um zu vermeiden, da\ss Stackfaults undeterministisches Zeitverhalten verursachen \end{itemize} -Eine Ausgezeichnete Einführung zum Erstellen von Echtzeitapplikationen und zur +Eine Ausgezeichnete Einf\"uhrung zum Erstellen von Echtzeitapplikationen und zur Verwendung von Preempt RT findet sich unter:\newline http://rt.wiki.kernel.org -\paragraph{Tracing / Latenzen aufspüren} +\paragraph{Tracing / Latenzen aufsp\"uren} \subparagraph{FTrace} -Ein hervorragendes Werkzeug, um kernelseitige Codepfade aufzuspüren, die lange -Latenzzeiten verursachen, ist Ftrace. Ftrace wird über DebugFS, einem virtuellen +Ein hervorragendes Werkzeug, um kernelseitige Codepfade aufzusp\"uren, die lange +Latenzzeiten verursachen, ist Ftrace. Ftrace wird \"uber DebugFS, einem virtuellen Dateisystem, gesteuert und platziert dort auch seine Ausgaben. Die einfachste Methode, FTrace zu verwenden ist Cyclictest. Cyclictest biete bereits einige -Optionen, um FTrace zu steuern. Die Option -f schällt Cyclictests Ftrace -Support an, -b <max\_latency> veranlaßt Cyclictest, bei Überschreiten einer +Optionen, um FTrace zu steuern. Die Option -f sch\"allt Cyclictests Ftrace +Support an, -b <max\_latency> veranla\ss t Cyclictest, bei \"Uberschreiten einer maximalen Latenzzeit, abzubrechen und einen Trace zu triggern. -\subparagraph{Kerneloptionen für FTrace} -Um FTrace verwenden zu können, müssen beim Konfigurieren des Kernels einige +\subparagraph{Kerneloptionen f\"ur FTrace} +Um FTrace verwenden zu k\"onnen, m\"ussen beim Konfigurieren des Kernels einige unter dem Menupunkt ''Kernel hacking-->Tracers'' einige Optionen aktiviert werden: \begin{itemize} \item Kernel Function Tracer \item Beliebige Optionen, die mit Trace beginnen (der zu verwendende -Tracetyp kann cyclictest über die Commandline mitgegeben werden, siehe +Tracetyp kann cyclictest \"uber die Commandline mitgegeben werden, siehe cyclictest -h. Default ist der Event Tracer) \end{itemize} \subparagraph{Beispiel eines Traces} -Das Erstellen eines Traces mit cyclictest läßt sich am Besten mit einem Beispiel -erläutern: +Das Erstellen eines Traces mit cyclictest l\"a\ss t sich am Besten mit einem Beispiel +erl\"autern: \begin{lstlisting} # mount DebugFS mkdir -p /mnt/debugfs @@ -290,7 +290,7 @@ IRQ-129-772 [000] 4154503386.851234: timer_interrupt<-ret_from \paragraph{Kontrollfragen} \begin{itemize} -\item Welche Optionen sollten beim Übersetzen eines Preempt RT Kernels +\item Welche Optionen sollten beim \"Ubersetzen eines Preempt RT Kernels mindestens gesetzt sein? \item Wozu dient das Tool cyclictest? \item Welchen bekannten ''Pitfall'' gibt es bzgl. hoher Latencies mit Floodping |
