|
Vorwort |
6 |
|
|
Inhaltsverzeichnis |
8 |
|
|
1 Einleitung |
12 |
|
|
2 Theorie ist notwendig |
18 |
|
|
2.1 Betriebssystemarchitektur |
18 |
|
|
2.1.1 Komponenten des Kernels |
19 |
|
|
2.1.2 Sonstige Betriebssystemkomponenten |
30 |
|
|
2.2 Abarbeitungskontext und Unterbrechungsmodell |
30 |
|
|
2.3 Quellensuche |
32 |
|
|
3 Treiberentwicklung in der Praxis |
36 |
|
|
3.1 Auf der Kommandoebene entwickeln |
37 |
|
|
3.2 Techniken der Treiberprogrammierung |
53 |
|
|
3.2.1 Coding Style: Kernelcode lesen und Kernelcode schreiben |
53 |
|
|
3.2.2 Kernelcode kodieren |
55 |
|
|
3.2.3 Objektbasierte Programmierung im Kernel |
57 |
|
|
3.3 Nicht vergessen: Auswahl einer geeigneten Lizenz |
60 |
|
|
3.3.1 GPL und LGPL |
61 |
|
|
3.3.2 MPL und BSD |
62 |
|
|
4 Treiber aus Sicht der Applikation |
64 |
|
|
4.1 Die Programmierschnittstelle der Applikation |
64 |
|
|
4.2 Zugriffsmodi |
69 |
|
|
5 Einfache Treiber |
74 |
|
|
5.1 Bevor es losgeht ... |
75 |
|
|
5.2 Den Kernel erweitern |
77 |
|
|
5.2.1 Kernelmodule |
77 |
|
|
5.2.2 Vom Modul zum Treiber |
81 |
|
|
5.2.3 Gerätenummern ersetzen Major-Nummern |
84 |
|
|
5.3 Die Treiber-Einsprungspunkte |
88 |
|
|
5.3.1 driver_open: die Zugriffskontrolle |
90 |
|
|
5.3.2 Aufräumen in driver_close |
92 |
|
|
5.3.3 driver_read liefert die Daten |
93 |
|
|
5.3.4 Schreibzugriffe im Treiber |
97 |
|
|
5.3.5 Die Universalschnittstelle IO-Control |
98 |
|
|
5.3.6 Wenn Applikationen mehrere Ein-/Ausgabekanäle überwachen |
100 |
|
|
5.4 Daten zwischen Kernel- und User-Space transferieren |
106 |
|
|
5.5 Hardware anbinden |
109 |
|
|
5.5.1 Ressourcen-Management |
110 |
|
|
5.5.2 Datentypen und Datenablage |
119 |
|
|
5.5.3 Direkter Hardwarezugriff |
121 |
|
|
5.5.4 Hardware erkennen |
126 |
|
|
5.5.5 PCI |
130 |
|
|
5.6 Zugriffsmodi im Treiber realisieren |
141 |
|
|
5.7 Treiberinstanzen |
145 |
|
|
6 Fortgeschrittene Treiberentwicklung |
148 |
|
|
6.1 Zunächst die Übersicht |
148 |
|
|
6.2 Interruptbetrieb |
150 |
|
|
6.3 Softirqs |
155 |
|
|
6.3.1 Tasklets |
156 |
|
|
6.3.2 Timer-Funktionen |
159 |
|
|
6.4 Kernel-Threads |
163 |
|
|
6.4.1 Workqueues |
167 |
|
|
6.4.2 Event-Workqueue |
171 |
|
|
6.5 Kritische Abschnitte sichern |
172 |
|
|
6.5.1 Atomare Operationen |
173 |
|
|
6.5.2 Semaphore |
177 |
|
|
6.5.3 Spinlocks |
182 |
|
|
6.5.4 Sequencelocks |
187 |
|
|
6.5.5 Interruptsperre und Kernel-Lock |
190 |
|
|
6.5.6 Synchronisiert warten |
191 |
|
|
6.5.7 Memory Barriers |
194 |
|
|
6.5.8 Fallstricke |
195 |
|
|
6.6 Vom Umgang mit Zeiten |
197 |
|
|
6.6.1 Relativ- und Absolutzeiten |
197 |
|
|
6.6.2 Zeitverzögerungen |
201 |
|
|
7 Systemaspekte |
204 |
|
|
7.1 Proc-Filesystem |
205 |
|
|
7.1.1 Der lesende Zugriff auf die Proc-Datei |
209 |
|
|
7.1.2 Schreibzugriffe unterstützen |
213 |
|
|
7.1.3 Sequence-Files |
214 |
|
|
7.2 Das neue Gerätemodell |
221 |
|
|
7.2.1 Treiber anmelden |
224 |
|
|
7.2.2 Geräte anmelden |
225 |
|
|
7.2.3 Geräteklassen |
226 |
|
|
7.2.4 Attributdateien erstellen |
231 |
|
|
7.2.5 Neue Bussysteme anlegen |
235 |
|
|
7.3 Device-Filesystem |
235 |
|
|
7.4 Treiber parametrieren |
239 |
|
|
7.5 Systemintegration |
242 |
|
|
7.5.1 Modutils |
243 |
|
|
7.5.2 Hotplug |
245 |
|
|
7.6 Kernel Build System |
248 |
|
|
7.6.1 Treiberquellen als integrative Erweiterung der Kernelquellen |
249 |
|
|
7.6.2 Modultreiber außerhalb der Kernelquellen |
252 |
|
|
7.7 Intermodul-Kommunikation |
255 |
|
|
8 Sonstige Treibersubsysteme |
260 |
|
|
8.1 Blockorientierte Gerätetreiber |
260 |
|
|
8.1.1 Bevor es richtig losgeht ... |
263 |
|
|
8.1.2 Daten kerneloptimiert transferieren |
264 |
|
|
8.1.3 Grundlegendes zu BIO-Blöcken |
269 |
|
|
8.1.4 Treiberoptimierter Datentransfer |
273 |
|
|
8.2 USB-Subsystem |
275 |
|
|
8.2.1 USB programmtechnisch betrachtet |
276 |
|
|
8.2.2 Den Treiber beim USB-Subsystem registrieren |
280 |
|
|
8.2.3 Die Geräteinitialisierung und die -deinitialisierung |
282 |
|
|
8.2.4 Auf das USB-Gerät zugreifen |
283 |
|
|
8.3 Netzwerk-Subsystem |
290 |
|
|
8.3.1 Datenaustausch zur Kommunikation |
290 |
|
|
8.3.2 Geräteinitialisierung |
294 |
|
|
8.3.3 Netzwerktreiber deinitialisieren |
296 |
|
|
8.3.4 Start und Stopp des Treibers |
296 |
|
|
8.3.5 Senden und Empfangen |
297 |
|
|
9 Über das Schreiben eines guten, performanten Treibers |
304 |
|
|
9.1 Konzeption |
304 |
|
|
9.1.1 Keine halben Sachen ... |
305 |
|
|
9.1.2 Intuitive Nutzung durch Struktur |
306 |
|
|
9.1.3 Sicher muss es sein |
307 |
|
|
9.1.4 Funktional muss es sein |
307 |
|
|
9.2 Realisierung |
308 |
|
|
9.2.1 Sicherheitsgerichtetes Programmieren |
308 |
|
|
9.2.2 Mit Stil programmieren |
309 |
|
|
9.3 Echtzeitaspekte |
313 |
|
|
Anhang |
318 |
|
|
A Kernel generieren und installieren |
320 |
|
|
B Portierungs-Guide |
324 |
|
|
C Makros und Funktionen des Kernels kurz gefasst |
332 |
|
|
D Literatur- und Quellennachweis |
422 |
|
|
Stichwortverzeichnis |
424 |
|