summaryrefslogtreecommitdiff
path: root/kernel-devel/uio-driver/handout_uio-driver_de.tex
diff options
context:
space:
mode:
Diffstat (limited to 'kernel-devel/uio-driver/handout_uio-driver_de.tex')
-rw-r--r--kernel-devel/uio-driver/handout_uio-driver_de.tex510
1 files changed, 255 insertions, 255 deletions
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}