diff options
Diffstat (limited to 'kernel-devel/uio-driver')
11 files changed, 1742 insertions, 10 deletions
diff --git a/kernel-devel/uio-driver/handout_uio-driver_de.tex b/kernel-devel/uio-driver/handout_uio-driver_de.tex index 4c391b2..546c7fe 100644 --- a/kernel-devel/uio-driver/handout_uio-driver_de.tex +++ b/kernel-devel/uio-driver/handout_uio-driver_de.tex @@ -1,17 +1,602 @@ -\documentclass{article} +\documentclass{lxarticle} \usepackage{german} \usepackage[utf8]{inputenc} +\usepackage{lxheaders} +\usepackage{lxextras} \begin{document} -\section*{Titel} +\section*{Linux-Treiber im Userspace} -\subsection*{Abschnitt1} +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 +verlagern. Dies vereinfacht die Entwicklung und Wartung von Treibern, +außerdem ergeben sich Möglichkeiten, die besonders Industriebetrieben +entgegen kommen. -Text +Eine im Automatisierungsbereich tätige 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 +Linux-Horror-Story begonnen. -\subsection*{Abschnitt2} +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 +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. +Treibercode mit mehreren tausend Codezeilen ist keine Seltenheit. -Text +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 +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 +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 +unerfreuliche Tage vor sich. + +Das zuletzt genannte Problem löst 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 +Unermessliche wachsen. Zweitens geht der Aufnahme von Code in den Mainline-Kernel +gewöhnlich 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 +Industriebetriebe genehmigen ihren Programmierern diesen Zusatzaufwand, da der +Treiber in ihrer Maschine ja schon läuft. + +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 +(meist illegale) Tricks angewandt, um dieser Bedingung der GPL zu entgehen und +ihren Kernelcode unter Verschluss zu halten. + +\subsection*{UIO löst Probleme} + +Die geschilderte Problematik führte bereits vor längerer Zeit zu Überlegungen, +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 +\cmd{mmap()} in den Userspace zu mappen. Damit kann man bereits alle Register +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. + +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 +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 +kundenspezifischen Kerneltreiber wird lediglich eine Struktur vom Typ +\cmd{struct uio\_info} mit einigen Informationen gefüllt 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 +(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 +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. + +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 +Beschreiben von Registern die Hardware initialisieren, so dass sie die +gewünschte Funktion ausführt 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 +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. + +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 +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 +\cmd{read()} erkennen Sie, wie viele Interrupts Sie verpasst haben. + +\subsection*{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 +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 +entstand eine wochenlange Diskussion, die schnell vom eigentlichen Thema +abwich und sich hauptsächlich mit der Lizensierungs-Problematik beschäftigte. + +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 +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 +verzichten. Durch UIO wird an dieser Stelle ein gangbarer und legaler Ausweg +geschaffen. + +\subsection*{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()}, +\cmd{write()} und \cmd{ioctl()} zugegriffen werden kann. + +\begin{figure}[h] +\centering +\includegraphics[width=0.8\textwidth]{images/konventioneller-treiber_de.png} +\caption{Aufbau eines konventionellen Treibers} +\label{img:konvtreiber} +\end{figure} + + + +Alle diese Funktionen +müssen vollständig im Treiber implementiert werden und führen je nach Gerät +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 +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 +mehr ioctl-Unterfunktionen implementieren. + +\begin{figure}[h] +\centering +\includegraphics[width=0.8\textwidth]{images/ioctl-vs-uio_de.png} +\caption{Vergleich von \cmd{ioctl()}-basierten Sytemen mit UIO} +\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 +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 +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 +\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. + +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 +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 +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, +erfordert das Debugging doch erheblich mehr an Spezialwissen als im Userspace. +In einem Kerneltreiber können 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 +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. + +\subsection*{...und UIO-Treiber} + +Sieht man sich Gerätetreiber 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 +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. + +\begin{figure}[h] +\centering +\includegraphics[width=0.8\textwidth]{images/uio-treiber_de.png} +\caption{Aufbau eines konventionellen Treibers} +\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 +in den Userspace zu mappen. Im Falle einer PCI-Karte erhalten Sie die +Informationen über Startadresse und Länge 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 +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 +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 +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, +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 +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. + +Der ganze Rest, also die komplette eigentliche Funktionalität 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 +Kenntnisse und Tools, als sie zur Programmierung ihrer Applikation ohnehin +benötigen. + +Im Beispiel oben haben wir gesehen, welchen Aufwand es bedeutet, einen +einzelnen Wert per \cmd{ioctl()} in ein Hardware-Register zu befördern. 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. + +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 +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 +ein Update des Treibers durch nichts von einem Update der Anwender-Applikation. + +\subsection*{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 +einem Jahr, beispielsweise im Zuge eines allgemeinen Software-Updates auf einen +aktuellen Kernel wechseln, so sind oft deutliche Änderungen am Kerneltreiber +nötig. + +Konventionelle Treiber beinhalten zwangsläufig 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 +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 +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. + +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 +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 +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. + +Dennoch sollten sie den Kernelteil ihres Treibers möglichst 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. + +\subsection*{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 +2.6.23-rc1 im Mainline-Kernel. + +Der Treiber unterscheidet sich zunächst 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 +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. + +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: + +\begin{lstlisting} +/* Struktur anlegen */ +struct uio_info *info; +info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); +/* Name und Version setzen */ +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 +(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: + +\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: + +\begin{lstlisting} +info->irq_flags = IRQF_DISABLED | IRQF_SHARED; +\end{lstlisting} + +Die Adresse des (noch zu erstellenden) Interrupt-Handlers darf natürlich +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 +physikalischen Speicher handelt: + +\begin{lstlisting} +info->mem[0].addr = pci_resource_start(dev, 0); +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 +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 +Kernel verwendbaren Bereich: + +\begin{lstlisting} +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 +UIO-Framework registrieren: + +\begin{lstlisting} +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 +\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 +weggelassen. + +Damit das Ganze funktioniert, muss natürlich noch der oben angegebene +Interrupt-Handler implementiert werden. Sein Gerüst sieht so aus: + +\begin{lstlisting} +static irqreturn_t mein_irq_handler(int irq, struct uio_info *dev_info) +{ + void *ptr = dev_info->mem[0].internal_addr; + + if (Interrupt_kam_nicht_von_meiner_Karte) + return IRQ_NONE; +\end{lstlisting} + + Hier sind Zugriffe mit Hilfe von ioread/iowrite möglich: + +\begin{lstlisting} + ein_byte = ioread8(ptr + MEIN_REGISTER_OFFSET); + iowrite8(ein_byte | INTERRUPT_AUS, ptr + NOCH_EIN_OFFSET); + + Hier muss sichergestellt sein, dass die Interruptleitung + wieder inaktiv ist! + + return IRQ_HANDLED; +} +\end{lstlisting} + +Jetzt ist der Kernel-Teil des Treibers komplett. Beispiele für vollständige +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 +\cmd{Documentation/DocBook/uio-howto.tmpl}; mit \cmd{make htmldocs} erstellt +man daraus eine lesbare Form. + +\subsection*{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 +mehrere UIO-Devices gleichzeitig testen will. Hier hilft ein kleines Tool +namens \cmd{lsuio}, das alle diese Werte übersichtlich auflistet. + +Der Sourcecode dieses Tools findet sich auf dem Server des OSADL. Nach dem +Auspacken des Archivs erstellt das übliche + +\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 +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 +voraussetzen, dass das eigene Device immer als \cmd{/dev/uio0} erscheint. +Durch Überprüfen der Dateien \cmd{name} und \cmd{version} in den Verzeichnissen +unterhalb von \cmd{/sys/class/uio} kann man diese Informationen auf sichere +Weise gewinnen. + +\subsection*{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: + +\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 +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 +der Karte zugegriffen werden kann. Der Treiber wird jetzt die Register der +Karte mit sinnvollen Werten beschreiben. Zuletzt wird er dafür 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. +Dabei liest er einen vorzeichenbehafteten 32-bit-Wert. Da \cmd{read()} +standardmäßig blockiert, wenn bei \cmd{open()} kein \cmd{O\_NONBLOCK} +angegeben wurde, sieht das einfach so aus: + +\begin{lstlisting} +s32 irq_count; + +while (read(fd, &irq_count, 4)==4) { + +/* Interrupt-Aktionen */ + +} +\end{lstlisting} + +Natürlich 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. + +Will man gleichzeitig auf mehrere Filedeskriptoren warten, z.B. auf +Interrupts des UIO-Device und auf das Eintreffen von Bytes in einem +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 +Anwender-Applikation. + +\subsection*{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 +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. + +Auch Hardware, die keine Interrupts erzeugt, ist kein idealer Kandidat für +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 +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 +zeigen, ob an dieser Stelle Nachfrage besteht. + +\subsection*{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 +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. + +Hat man sich einmal für 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 +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. \end{document} diff --git a/kernel-devel/uio-driver/images/ioctl-vs-uio_de.png b/kernel-devel/uio-driver/images/ioctl-vs-uio_de.png Binary files differnew file mode 100644 index 0000000..0989d07 --- /dev/null +++ b/kernel-devel/uio-driver/images/ioctl-vs-uio_de.png diff --git a/kernel-devel/uio-driver/images/ioctl-vs-uio_de.svg b/kernel-devel/uio-driver/images/ioctl-vs-uio_de.svg new file mode 100644 index 0000000..a913a69 --- /dev/null +++ b/kernel-devel/uio-driver/images/ioctl-vs-uio_de.svg @@ -0,0 +1,383 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/hans/linutronix/articles/uio-ct-artikel_v2" + sodipodi:docname="ioctl-vs-uio.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + inkscape:export-filename="/home/hans/linutronix/articles/uio-ct-artikel_v2/ioctl-vs-uio.png" + inkscape:export-xdpi="100" + inkscape:export-ydpi="100"> + <defs + id="defs4"> + <marker + inkscape:stockid="Arrow1Mend" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Mend" + style="overflow:visible;"> + <path + id="path3262" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" + transform="scale(0.4) rotate(180) translate(10,0)" /> + </marker> + <marker + inkscape:stockid="Arrow2Mend" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow2Mend" + style="overflow:visible;"> + <path + id="path3280" + style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;" + d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " + transform="scale(0.6) rotate(180) translate(0,0)" /> + </marker> + <marker + inkscape:stockid="TriangleOutM" + orient="auto" + refY="0.0" + refX="0.0" + id="TriangleOutM" + style="overflow:visible"> + <path + id="path3254" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.4)" /> + </marker> + <marker + inkscape:stockid="TriangleInM" + orient="auto" + refY="0.0" + refX="0.0" + id="TriangleInM" + style="overflow:visible"> + <path + id="path3245" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(-0.4)" /> + </marker> + <marker + inkscape:stockid="Arrow1Mstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Mstart" + style="overflow:visible"> + <path + id="path3159" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.4) translate(10,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lstart" + style="overflow:visible"> + <path + id="path3153" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.8) translate(12.5,0)" /> + </marker> + <marker + inkscape:stockid="Arrow2Mstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow2Mstart" + style="overflow:visible"> + <path + id="path3177" + style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round" + d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " + transform="scale(0.6) translate(0,0)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.4" + inkscape:cx="246.67635" + inkscape:cy="792.61315" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1672" + inkscape:window-height="977" + inkscape:window-x="0" + inkscape:window-y="0"> + <sodipodi:guide + orientation="vertical" + position="69.285714" + id="guide3134" /> + <sodipodi:guide + orientation="vertical" + position="372.85714" + id="guide3136" /> + <sodipodi:guide + orientation="horizontal" + position="956.42857" + id="guide3140" /> + <sodipodi:guide + orientation="horizontal" + position="772.85714" + id="guide3142" /> + <sodipodi:guide + orientation="horizontal" + position="631.42857" + id="guide2349" /> + <sodipodi:guide + orientation="horizontal" + position="682.14286" + id="guide2351" /> + <sodipodi:guide + orientation="vertical" + position="665" + id="guide2353" /> + <sodipodi:guide + orientation="horizontal" + position="587.14286" + id="guide2357" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1"> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1" + d="M 67.857143,393.07647 L 665,393.07647" + id="path2160" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1" + d="M 68.214289,165.93362 L 664.64285,165.93362" + id="path3138" + sodipodi:nodetypes="cc" /> + <rect + style="fill:#fc5400;fill-opacity:1;stroke:#000000;stroke-width:2.06220484;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect3146" + width="199.28641" + height="100.71439" + x="272.45969" + y="180.93361" + ry="10" + rx="10" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="68.571426" + y="283.07645" + id="text3398" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3400" + x="68.571426" + y="283.07645">Kernelspace</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="68.520004" + y="146.75792" + id="text3402" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan2243" + x="68.520004" + y="146.75792">Hardware</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="68.520004" + y="446.22791" + id="text3408" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3412" + x="68.520004" + y="446.22791">Userspace</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="-267.33499" + y="265.69397" + id="text3436" + sodipodi:linespacing="100%" + transform="matrix(0,-1,1,0,0,0)"><tspan + sodipodi:role="line" + id="tspan3440" + x="-267.33499" + y="265.69397">Treiber</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch" + x="333.15143" + y="465.7879" + id="text3442" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan2247" + x="333.15143" + y="465.7879">ioctl()</tspan></text> + <rect + style="fill:#fc9900;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect3492" + width="99.999985" + height="49.285713" + x="323.21429" + y="368.43359" + rx="10" + ry="10" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch" + x="331.07361" + y="398.45221" + id="text3494" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan2245" + x="331.07361" + y="398.45221">syscall</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch" + x="278.52625" + y="256.12363" + id="text2249" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan2253" + x="278.52625" + y="256.12363">copy_from_user()</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch" + x="316.38339" + y="214.69505" + id="text2255" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan2259" + x="316.38339" + y="214.69505">iowrite()</tspan></text> + <rect + style="fill:#fc9900;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect2261" + width="99.999985" + height="49.285713" + x="322.85718" + y="299.14789" + rx="10" + ry="10" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch" + x="355.0022" + y="329.1665" + id="text2263" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan2267" + x="355.0022" + y="329.1665">VFS</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 373.57142,339.33983 L 373.57142,381.48268" + id="path3470" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 373.57142,267.91124 L 373.57142,310.05409" + id="path2269" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 372.85714,407.19696 L 372.85714,449.33981" + id="path2271" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 374.28571,152.91125 L 374.28571,195.0541" + id="path2273" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 587.14285,449.50503 L 587.14285,154.50503" + id="path2277" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch" + x="547.81189" + y="465.4093" + id="text3450" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3456" + x="547.81189" + y="465.4093">a[n]=b;</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1" + d="M 497.14286,492.67901 L 497.14286,96.964715" + id="path3458" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="306.89368" + y="95.47361" + id="text3460" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3464" + x="306.89368" + y="95.47361">a) mit ioctl():</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="507.18765" + y="95.509331" + id="text3466" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3470" + x="507.18765" + y="95.509331">b) mit mmap():</tspan></text> + </g> +</svg> diff --git a/kernel-devel/uio-driver/images/ioctl-vs-uio.png b/kernel-devel/uio-driver/images/ioctl-vs-uio_en.png Binary files differindex 8536934..8536934 100644 --- a/kernel-devel/uio-driver/images/ioctl-vs-uio.png +++ b/kernel-devel/uio-driver/images/ioctl-vs-uio_en.png diff --git a/kernel-devel/uio-driver/images/konventioneller-treiber_de.png b/kernel-devel/uio-driver/images/konventioneller-treiber_de.png Binary files differnew file mode 100644 index 0000000..cbca8bc --- /dev/null +++ b/kernel-devel/uio-driver/images/konventioneller-treiber_de.png diff --git a/kernel-devel/uio-driver/images/konventioneller-treiber_de.svg b/kernel-devel/uio-driver/images/konventioneller-treiber_de.svg new file mode 100644 index 0000000..5dbd773 --- /dev/null +++ b/kernel-devel/uio-driver/images/konventioneller-treiber_de.svg @@ -0,0 +1,332 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/hans/linutronix/articles/uio-ct-artikel/bilder" + sodipodi:docname="konventioneller-treiber.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + inkscape:export-filename="/home/hans/linutronix/articles/uio-ct-artikel/bilder/konventioneller-treiber.png" + inkscape:export-xdpi="100" + inkscape:export-ydpi="100"> + <defs + id="defs4"> + <marker + inkscape:stockid="TriangleOutM" + orient="auto" + refY="0.0" + refX="0.0" + id="TriangleOutM" + style="overflow:visible"> + <path + id="path3254" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.4)" /> + </marker> + <marker + inkscape:stockid="TriangleInM" + orient="auto" + refY="0.0" + refX="0.0" + id="TriangleInM" + style="overflow:visible"> + <path + id="path3245" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(-0.4)" /> + </marker> + <marker + inkscape:stockid="Arrow1Mstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Mstart" + style="overflow:visible"> + <path + id="path3159" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.4) translate(10,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lstart" + style="overflow:visible"> + <path + id="path3153" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.8) translate(12.5,0)" /> + </marker> + <marker + inkscape:stockid="Arrow2Mstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow2Mstart" + style="overflow:visible"> + <path + id="path3177" + style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round" + d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " + transform="scale(0.6) translate(0,0)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.4" + inkscape:cx="246.67635" + inkscape:cy="796.87607" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1672" + inkscape:window-height="977" + inkscape:window-x="0" + inkscape:window-y="0"> + <sodipodi:guide + orientation="vertical" + position="69.285714" + id="guide3134" /> + <sodipodi:guide + orientation="vertical" + position="633.57143" + id="guide3136" /> + <sodipodi:guide + orientation="horizontal" + position="956.42857" + id="guide3140" /> + <sodipodi:guide + orientation="horizontal" + position="872.85714" + id="guide3142" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1"> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1" + d="M 67.142857,339.50504 L 637.14285,339.50504" + id="path2160" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1" + d="M 66.785718,268.79076 L 639.64285,268.79076" + id="path3138" + sodipodi:nodetypes="cc" /> + <rect + style="fill:#f2f000;fill-opacity:1;stroke:#000000;stroke-width:2.06220484;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect3144" + width="253.57143" + height="158.57143" + x="215.71428" + y="96.964714" /> + <rect + style="fill:#fc5400;fill-opacity:1;stroke:#000000;stroke-width:2.06220484;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect3146" + width="120" + height="158.57143" + x="512.85712" + y="96.647896" + ry="10" + rx="10" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.71429,123.07647 L 520,123.07647" + id="path3148" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.19192,144.50504 L 519.47763,144.50504" + id="path3352" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.19192,165.21932 L 519.47763,165.21932" + id="path3354" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.19192,186.64789 L 519.47763,186.64789" + id="path3356" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.19191,207.36218 L 519.47762,207.36218" + id="path3358" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.19192,228.07647 L 519.47763,228.07647" + id="path3360" /> + <rect + style="fill:#fc9900;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect3382" + width="122.14286" + height="49.285713" + x="511.42856" + y="279.50504" + rx="10" + ry="10" /> + <rect + style="fill:#0fe400;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect3384" + width="418.57144" + height="90" + x="215" + y="371.64789" + rx="10" + ry="10" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 534.28571,331.83982 L 534.28571,388.98267" + id="path3386" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 571.42858,332.55409 L 571.42858,388.98266" + id="path3388" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 606.42857,331.83981 L 606.42857,388.98266" + id="path3390" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4.54251957;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInM);marker-end:url(#TriangleOutM);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 575.00001,256.64789 L 575.00001,280.21932" + id="path3392" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="68.571426" + y="179.50504" + id="text3398" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3400" + x="68.571426" + y="179.50504">Kernelspace</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="67.805717" + y="310.32935" + id="text3402" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3406" + x="67.805717" + y="310.32935">Interface</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="67.805717" + y="421.04361" + id="text3408" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3412" + x="67.805717" + y="421.04361">Userspace</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="356.19702" + y="421.7579" + id="text3414" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3418" + x="356.19702" + y="421.7579">Applikation</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="328.55521" + y="159.61504" + id="text3420" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3430" + x="331.32864" + y="159.61504">interne </tspan><tspan + sodipodi:role="line" + id="tspan3432" + x="328.55521" + y="179.61504">Kernelfunktionen</tspan><tspan + sodipodi:role="line" + id="tspan3434" + x="328.55521" + y="199.61504">(instabiles API)</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="538.3443" + y="180.13646" + id="text3436" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3440" + x="538.3443" + y="180.13646">Treiber</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch" + x="524.28571" + y="310.21933" + id="text3442" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3444" + x="524.28571" + y="310.21933">/dev/xyz</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch" + x="533.32349" + y="408.64072" + id="text3446" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3450" + x="533.32349" + y="408.64072">read()</tspan><tspan + sodipodi:role="line" + id="tspan3452" + x="533.32349" + y="428.64072">write()</tspan><tspan + sodipodi:role="line" + id="tspan3454" + x="533.32349" + y="448.64072">ioctl()</tspan></text> + </g> +</svg> diff --git a/kernel-devel/uio-driver/images/konventioneller-treiber.png b/kernel-devel/uio-driver/images/konventioneller-treiber_en.png Binary files differindex bea54da..bea54da 100644 --- a/kernel-devel/uio-driver/images/konventioneller-treiber.png +++ b/kernel-devel/uio-driver/images/konventioneller-treiber_en.png diff --git a/kernel-devel/uio-driver/images/uio-treiber_de.png b/kernel-devel/uio-driver/images/uio-treiber_de.png Binary files differnew file mode 100644 index 0000000..9e18a06 --- /dev/null +++ b/kernel-devel/uio-driver/images/uio-treiber_de.png diff --git a/kernel-devel/uio-driver/images/uio-treiber_de.svg b/kernel-devel/uio-driver/images/uio-treiber_de.svg new file mode 100644 index 0000000..a1cc780 --- /dev/null +++ b/kernel-devel/uio-driver/images/uio-treiber_de.svg @@ -0,0 +1,433 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/hans/linutronix/articles/uio-ct-artikel_v2" + sodipodi:docname="uio-treiber.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + inkscape:export-filename="/home/hans/linutronix/articles/uio-ct-artikel_v2/uio-treiber.png" + inkscape:export-xdpi="100" + inkscape:export-ydpi="100"> + <defs + id="defs4"> + <marker + inkscape:stockid="TriangleOutM" + orient="auto" + refY="0.0" + refX="0.0" + id="TriangleOutM" + style="overflow:visible"> + <path + id="path3254" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.4)" /> + </marker> + <marker + inkscape:stockid="TriangleInM" + orient="auto" + refY="0.0" + refX="0.0" + id="TriangleInM" + style="overflow:visible"> + <path + id="path3245" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(-0.4)" /> + </marker> + <marker + inkscape:stockid="Arrow1Mstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Mstart" + style="overflow:visible"> + <path + id="path3159" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.4) translate(10,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lstart" + style="overflow:visible"> + <path + id="path3153" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none" + transform="scale(0.8) translate(12.5,0)" /> + </marker> + <marker + inkscape:stockid="Arrow2Mstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow2Mstart" + style="overflow:visible"> + <path + id="path3177" + style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round" + d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " + transform="scale(0.6) translate(0,0)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.4" + inkscape:cx="246.67635" + inkscape:cy="749.98402" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1672" + inkscape:window-height="977" + inkscape:window-x="0" + inkscape:window-y="0"> + <sodipodi:guide + orientation="vertical" + position="69.285714" + id="guide3134" /> + <sodipodi:guide + orientation="vertical" + position="632.14286" + id="guide3136" /> + <sodipodi:guide + orientation="horizontal" + position="956.42857" + id="guide3140" /> + <sodipodi:guide + orientation="horizontal" + position="772.85714" + id="guide3142" /> + <sodipodi:guide + orientation="horizontal" + position="631.42857" + id="guide2349" /> + <sodipodi:guide + orientation="horizontal" + position="682.14286" + id="guide2351" /> + <sodipodi:guide + orientation="vertical" + position="404.28571" + id="guide2353" /> + <sodipodi:guide + orientation="horizontal" + position="580.71429" + id="guide2357" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="fill:#0fe400;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect2347" + width="227.85715" + height="99.285751" + x="404.28571" + y="371.29074" + rx="10" + ry="10" /> + <path + style="fill:#f5cb00;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220472;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1" + d="M 469.28571,97.362184 L 469.28571,255.21932 L 503.57143,255.21932 L 503.57143,198.79075 L 632.14286,198.79075 L 632.14286,97.362184 L 469.28571,97.362184 z " + id="path3458" + sodipodi:nodetypes="ccccccc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1" + d="M 67.142857,339.50504 L 637.14285,339.50504" + id="path2160" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.06220484;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.06220472, 2.06220472;stroke-dashoffset:0;stroke-opacity:1" + d="M 66.785718,268.79076 L 639.64285,268.79076" + id="path3138" + sodipodi:nodetypes="cc" /> + <rect + style="fill:#f2f000;fill-opacity:1;stroke:#000000;stroke-width:2.06220484;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect3144" + width="253.57143" + height="158.57143" + x="215.71428" + y="96.964714" /> + <rect + style="fill:#fc5400;fill-opacity:1;stroke:#000000;stroke-width:2.06220484;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect3146" + width="120.71497" + height="47.142963" + x="512.14288" + y="208.07648" + ry="10" + rx="10" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.71429,123.07647 L 487.14286,123.07647" + id="path3148" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.19192,144.50504 L 488.04906,144.50504" + id="path3352" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.19192,165.21932 L 488.04906,165.21932" + id="path3354" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.19192,186.64789 L 488.04906,186.64789" + id="path3356" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.19191,207.36218 L 487.33476,207.36218" + id="path3358" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 445.19192,228.07647 L 487.33477,228.07647" + id="path3360" + sodipodi:nodetypes="cc" /> + <rect + style="fill:#fc9900;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect3382" + width="122.14286" + height="49.285713" + x="511.42856" + y="279.50504" + rx="10" + ry="10" /> + <rect + style="fill:#0fe400;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect3384" + width="165.71431" + height="98.571426" + x="215" + y="371.64789" + rx="10" + ry="10" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 534.28571,331.83982 L 534.28571,388.98267" + id="path3386" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 571.42858,332.55409 L 571.42858,388.98266" + id="path3388" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 606.42857,331.83981 L 606.42857,388.98266" + id="path3390" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4.54251957;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInM);marker-end:url(#TriangleOutM);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 575.00001,256.64789 L 575.00001,280.21932" + id="path3392" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="68.571426" + y="179.50504" + id="text3398" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3400" + x="68.571426" + y="179.50504">Kernelspace</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="67.805717" + y="310.32935" + id="text3402" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3406" + x="67.805717" + y="310.32935">Interface</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="69.234291" + y="425.32932" + id="text3408" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3412" + x="69.234291" + y="425.32932">Userspace</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="231.19704" + y="426.7579" + id="text3414" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3484" + x="231.19704" + y="426.7579">Applikation</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="328.55521" + y="159.61504" + id="text3420" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3430" + x="331.32864" + y="159.61504">interne </tspan><tspan + sodipodi:role="line" + id="tspan3432" + x="328.55521" + y="179.61504">Kernelfunktionen</tspan><tspan + sodipodi:role="line" + id="tspan3434" + x="328.55521" + y="199.61504">(instabiles API)</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="536.91577" + y="237.99361" + id="text3436" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3440" + x="536.91577" + y="237.99361">Treiber</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch" + x="517.14282" + y="310.93362" + id="text3442" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3456" + x="517.14282" + y="310.93362">/dev/uioX</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch" + x="536.1806" + y="415.06927" + id="text3446" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3474" + x="536.1806" + y="415.06927">read()</tspan><tspan + sodipodi:role="line" + id="tspan3476" + x="536.1806" + y="435.06927">mmap()</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="564.77295" + y="132.99361" + id="text3460" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3466" + x="564.77295" + y="132.99361">UIO-</tspan><tspan + sodipodi:role="line" + id="tspan3468" + x="564.77295" + y="152.99361">Framework</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 525.71428,179.33982 L 525.71428,221.48267" + id="path3470" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 616.42857,179.33982 L 616.42857,221.48267" + id="path3472" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:FreeSans" + x="431.8024" + y="425.4736" + id="text3486" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3490" + x="431.8024" + y="425.4736">Treiber</tspan></text> + <rect + style="fill:#fc9900;fill-opacity:1;stroke:#000000;stroke-width:2.41653538;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect3492" + width="99.999985" + height="49.285713" + x="404.64285" + y="279.86218" + rx="10" + ry="10" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier 10 Pitch" + x="422.50214" + y="309.16647" + id="text3494" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan3498" + x="422.50214" + y="309.16647">sysfs</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4.54251957;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInM);marker-end:url(#TriangleOutM);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 485.71429,255.57646 L 485.71429,279.14789" + id="path3500" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.41653538;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 458.57142,331.83982 L 458.57142,388.98267" + id="path3502" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4.54251957;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInM);marker-end:url(#TriangleOutM);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 381.07143,421.64789 L 404.64286,421.64789" + id="path2355" /> + </g> +</svg> diff --git a/kernel-devel/uio-driver/images/uio-treiber.png b/kernel-devel/uio-driver/images/uio-treiber_en.png Binary files differindex caa2152..caa2152 100644 --- a/kernel-devel/uio-driver/images/uio-treiber.png +++ b/kernel-devel/uio-driver/images/uio-treiber_en.png diff --git a/kernel-devel/uio-driver/pres_uio-driver_en.tex b/kernel-devel/uio-driver/pres_uio-driver_en.tex index 8468894..ca9ff44 100644 --- a/kernel-devel/uio-driver/pres_uio-driver_en.tex +++ b/kernel-devel/uio-driver/pres_uio-driver_en.tex @@ -6,7 +6,6 @@ \usepackage{graphicx} \title{The Userspace I/O Framework (UIO)} -\author{Hans-Jürgen Koch} \institute{Linutronix GmbH} \begin{document} @@ -69,12 +68,12 @@ % ----- Slide "In-kernel driver" ------------------ \begin{frame} -\includegraphics[width=11cm]{images/konventioneller-treiber.png} +\includegraphics[width=11cm]{images/konventioneller-treiber_en.png} \end{frame} % ----- Slide "UIO driver" ------------------ \begin{frame} -\includegraphics[width=11cm]{images/uio-treiber.png} +\includegraphics[width=11cm]{images/uio-treiber_en.png} \end{frame} % ----- Slide "How UIO works" -------------------------- @@ -210,7 +209,7 @@ while (read(fd, &irq_cnt, 4)) { % ----- Slide "ioctl vs. UIO" ------------------ \begin{frame} -\includegraphics[width=10cm]{images/ioctl-vs-uio.png} +\includegraphics[width=10cm]{images/ioctl-vs-uio_en.png} \end{frame} % ----- Slide "Publish your driver!" -------------- |
