Linux-Treiber entwickeln (eBook)

Eine systematische Einführung in die Gerätetreiber- und Kernelprogrammierung - jetzt auch für Raspberry Pi
eBook Download: PDF | EPUB
2015 | 4. Auflage
688 Seiten
dpunkt (Verlag)
978-3-86491-756-1 (ISBN)

Lese- und Medienproben

Linux-Treiber entwickeln -  Jürgen Quade,  Eva-Katharina Kunst
Systemvoraussetzungen
Systemvoraussetzungen
49,90 inkl. MwSt
  • Download sofort lieferbar
  • Zahlungsarten anzeigen
Dieses Buch bietet eine systematische Einführung in die Kernelprogrammierung und in die Entwicklung von Gerätetreibern unter Linux - angefangen bei den Grundlagen bis hin zu speziellen Treibern und Techniken. Die innerhalb des Kernels nutzbaren Technologien werden umfassend vermittelt und mit vielen wiederverwertbaren Codebeispielen illustriert. Behandelt werden unter anderem: • die Architektur des Linux-Betriebssystems • die Programmierung von Tasklets, Kernel-Threads, Workqueues und hochauflösenden Timern • die Sicherung kritischer Abschnitte • effiziente Speicherverwaltung (Objekt-Caching) • die Systemintegration des Treibers (Proc-, Sysund Device-Filesystem) • das Kernel Build System • professionelle Hardwareanbindung für den Raspberry Pi • Green-Computing (Stromsparmodi) • Realzeitaspekte • spezielle Treiber (u.a. GPIO, I2C, PCI, USB, Blockgeräte) Hilfreich für die praktische Arbeit sind außerdem Programmiertricks erfahrener Kernelhacker, Code Templates als Ausgangspunkt für eigene Entwicklungen, ein eigenes Kapitel zum Entwurf guter und performanter Treiber sowie ein Anhang mit detaillierten Beschreibungen von mehr als 700 internen Kernelfunktionen. Das Buch richtet sich an Entwickler, Kernelhacker und Linux-Interessierte mit guten Programmierkenntnissen in der Sprache C. Einsteiger in Kernelprogrammierung, in Treiberentwicklung (und in Linux) erhalten eine praxisorientierte Einführung in das Thema. Profis, wie Entwickler eingebetteter Systeme, werden es auch als wertvolles Nachschlagewerk für die tägliche Arbeit einsetzen. Die 4. Auflage ist durchgehend auf den Stand des Kernels 4 aktualisiert worden. Ergänzt wurden Themen wie Cross-Entwicklung, Device Tree, GPIO, I2C und SPI sowie die Kernelcode-Entwicklung für eingebettete Systeme, insbesondere für den Raspberry Pi.

Jürgen Quade studierte Elektrotechnik an der TU München. Danach arbeitete er dort als Assistent am Lehrstuhl für Prozessrechner (heute Lehrstuhl für Realzeit-Computersysteme), promovierte und wechselte später in die Industrie, wo er im Bereich Prozessautomatisierung bei der Softing AG tätig war. Heute ist Jürgen Quade Professor an der Hochschule Niederrhein, wo er u.a. das Labor für Echtzeitsysteme betreut. Seine Schwerpunkte sind Echtzeitsysteme, Embedded Linux, Rechner- und Netzwerksicherheit sowie Open Source. Eva-Katharina Kunst studierte Kommunikationswissenschaft an der LMU München sowie Wirtschaftsinformatik an der Fachhochschule München. Sie ist freiberuflich tätig als Journalistin. IhreArbeitsgebiete sind Open Source, Linux und Knowledge Management.

Jürgen Quade studierte Elektrotechnik an der TU München. Danach arbeitete er dort als Assistent am Lehrstuhl für Prozessrechner (heute Lehrstuhl für Realzeit-Computersysteme), promovierte und wechselte später in die Industrie, wo er im Bereich Prozessautomatisierung bei der Softing AG tätig war. Heute ist Jürgen Quade Professor an der Hochschule Niederrhein, wo er u.a. das Labor für Echtzeitsysteme betreut. Seine Schwerpunkte sind Echtzeitsysteme, Embedded Linux, Rechner- und Netzwerksicherheit sowie Open Source. Eva-Katharina Kunst studierte Kommunikationswissenschaft an der LMU München sowie Wirtschaftsinformatik an der Fachhochschule München. Sie ist freiberuflich tätig als Journalistin. IhreArbeitsgebiete sind Open Source, Linux und Knowledge Management.

Einleitung 11
Theorie ist notwendig 19
Betriebssystemarchitektur 19
Komponenten des Kernels 20
Sonstige Betriebssystemkomponenten 33
Abarbeitungskontext und Unterbrechungsmodell 34
Quellensuche 37
Kernelcode-Entwicklung in der Praxis 41
Auf der Kommandoebene entwickeln 42
Fehler finden 52
Techniken der Kernelprogrammierung 62
Coding Style: Kernelcode lesen und Kernelcodeschreiben 62
Kernelcode kodieren 64
Objektbasierte Programmierung und Entwurfsmuster im Kernel 66
Hilfsfunktionen 70
Cross-Development 72
Nicht vergessen: Auswahl einer geeigneten Lizenz 74
GPL und LGPL 75
MPL und BSD 76
Treiber aus Sicht der Applikation 79
Die Programmierschnittstelle der Applikation 79
Zugriffsmodi 84
Einfache Treiber 89
Bevor es losgeht … 90
Cross-Kompilierung 92
Den Kernel erweitern 93
Kernelmodule 93
Vom Modul zum Treiber 98
Einfaches Treibertemplate 101
Die Treibereinsprungspunkte 105
driver_open: die Zugriffskontrolle 108
Aufräumen in driver_close 111
Lesezugriffe im Treiber 111
Schreibzugriffe im Treiber 121
Die Universalschnittstelle IO-Control 123
Wenn Applikationen mehrere Ein-/Ausgabekanäleüberwachen 127
Daten zwischen Kernel- und Userspace transferieren 130
Hardware anbinden 134
Datentypen und Datenablage 135
Ressourcenmanagement 136
Direkter Hardwarezugriff 145
Hardware erkennen 150
Device Tree 154
PCI 160
Treiberinstanzen 173
Treibertemplate: Basis für Eigenentwicklungen 175
Fortgeschrittene Kernelcode-Entwicklung 181
Zunächst die Übersicht 182
Interrupts 183
Interruptverarbeitung klassisch 183
Threaded Interrupts 187
Interrupts, testen mit dem Raspberry Pi 191
Softirqs 199
Tasklets 200
Timer-Funktionen 203
High Resolution Timer 207
Tasklet auf Basis des High Resolution Timers 210
Kernel-Threads 211
kthread-Daemon 213
Workqueues 216
Event-Workqueue 221
Kritische Abschnitte sichern 222
Atomare Operationen 223
Mutex und Semaphor 229
Spinlocks 240
Sequencelocks 247
Interruptsperre und Kernel-Lock 250
Synchronisiert warten 251
Memory Barriers 254
Per-CPU-Variablen 256
Fallstricke 256
Vom Umgang mit Zeiten 258
Relativ- und Absolutzeiten 258
Zeitverzögerungen 264
Dynamischen Speicher effizient verwalten 267
Buddy-System 268
Objekt-Caching 270
Große Speicherbereiche reservieren 275
Speicher pro Prozessorkern 276
Systemaspekte 281
Proc-Filesystem 282
Schreibzugriffe unterstützen 287
Sequencefiles 290
Das Gerätemodell 295
Implementierungstechnische Grundlagen 299
Gerätedateien automatisiert anlegen lassen 300
Treiber anmelden 302
Geräte anmelden 304
Attributdateien erstellen 310
Eigene Geräteklassen erstellen 314
Neue Bussysteme anlegen 315
Green Computing 316
Firmware-Interface 328
Treiber parametrieren 334
Systemintegration 339
Modutils 341
Hotplug 344
Module beim Booten laden 345
Kernel Build System 345
Treiberquellen als integrative Erweiterung der Kernelquellen 346
Modultreiber außerhalb der Kernelquellen 350
Module automatisiert generieren (DKMS) 352
Intermodul-Kommunikation 357
Realzeitaspekte 362
Sonstige Treibersubsysteme 367
GPIO-Subsystem 367
I2C-Subsystem 372
Serial Peripheral Interface (SPI) 380
USB-Subsystem 388
USB programmtechnisch betrachtet 389
Den Treiber beim USB-Subsystem registrieren 393
Die Geräteinitialisierung und die -deinitialisierung 395
Auf das USB-Gerät zugreifen 397
Netzwerk-Subsystem 403
Datenaustausch zur Kommunikation 404
Netzwerktreiber initialisieren 406
Netzwerktreiber deinitialisieren 407
Start und Stopp des Treibers 407
Senden und Empfangen 408
Blockorientierte Gerätetreiber 413
Bevor es richtig losgeht … 416
Daten kerneloptimiert transferieren 418
Grundlegendes zu BIO-Blöcken 424
Treiberoptimierter Datentransfer 428
Crypto-Subsystem 430
Kleines Einmaleins der Kryptografie 430
Dienste in der Übersicht 433
Eigene Algorithmen einbinden 444
Über das Schreiben eines guten, performanten Treibers 451
Konzeption 451
Keine halben Sachen … 452
Intuitive Nutzung durch Struktur 453
Sicher muss es sein 454
Funktional muss es sein 455
Realisierung 455
Sicherheitsgerichtetes Programmieren 455
Mit Stil programmieren 456
32 Bit und mehr: Portierbarer Code 461
Zeitverhalten 466
Anhang 471
Kernel generieren und installieren 473
Nativ kompilieren: PC-Plattform 475
Nativ kompilieren: Raspberry Pi 479
Cross-Kompilieren: PC als Host, Raspberry Pi als Target 480
Makros und Funktionen des Kernels kurz gefasst 485
Literaturverzeichnis 669
Index 671
www.dpunkt.de 0

1 Einleitung


Computersysteme bestehen aus einer Anzahl unterschiedlicher Hard- und Softwarekomponenten, deren Zusammenspiel erst die Abarbeitung komplexer Programme ermöglicht. Zu den Hardwarekomponenten gehören beispielsweise die eigentliche Verarbeitungseinheit, der Mikroprozessor mit dem Speicher, aber auch die sogenannte Peripherie, wie Tastatur, Maus, Monitor, LEDs oder Schalter. Diese Peripherie wird über Hardwareschnittstellen an die Verarbeitungseinheit angeschlossen. Hierfür haben sich Schnittstellen wie beispielsweise USB (Universal Serial Bus) oder im Bereich der eingebetteten Systeme auch I2C, SPI oder GPIO-Interfaces etabliert. Im PC-Umfeld ist PCI (Peripheral Component Interconnect) und PCI-Express verbreitet. Die Netzwerk- oder Grafikkarte wird beispielsweise über PCI-Express, Tastatur, Maus oder auch Drucker über USB mit dem Rechner verbunden.

Zentrale Komponente für den HW-Zugriff

Zu den Softwarekomponenten gehören das BIOS, das den Rechner nach dem Anschalten initialisiert, und das Betriebssystem. Das Betriebssystem koordiniert sowohl die Abarbeitung der Applikationen als auch die Zugriffe auf die Peripherie. Vielfach ersetzt man in diesem Kontext den Begriff Peripherie durch Hardware oder einfach durch Gerät, so dass das Betriebssystem den Zugriff auf die Hardware bzw. die Geräte steuert. Dazu muss es die unterschiedlichen Geräte kennen, bzw. es muss wissen, wie auf diese Geräte zugegriffen wird. Derartiges Wissen ist innerhalb des Betriebssystems in den Gerätetreibern hinterlegt. Sie stellen damit als Teil des Betriebssystemkerns die zentrale Komponente für den Hardwarezugriff dar. Ein Gerätetreiber ist eine Softwarekomponente, die aus einer Reihe von Funktionen besteht. Diese Funktionen wiederum steuern den Zugriff auf das Gerät.

Für jedes unterschiedliche Gerät wird ein eigener Treiber benötigt. So gibt es beispielsweise jeweils einen Treiber für den Zugriff auf die Festplatte, das Netzwerk oder die serielle Schnittstelle.

Da das Know-how über das Gerät im Regelfall beim Hersteller des Gerätes und nicht beim Programmierer des Betriebssystems liegt, sind innerhalb des Betriebssystemkerns Schnittstellen offengelegt, über die der vom Hersteller erstellte Treiber für das Gerät integriert werden kann. Kennt der Treiberprogrammierer diese Schnittstellen, kann er seinen Treiber erstellen und den Anwendern Zugriff auf die Hardware ermöglichen.

Der Anwender selbst greift auf die Hardware über ihm bekannte Schnittstellen zu. Bei einem Unix-System ist der Gerätezugriff dabei auf den Dateizugriff abgebildet. Jeder Programmierer, der weiß, wie er auf normale Dateien zugreifen kann, ist imstande, auch Hardware anzusprechen.

Für den Anwender eröffnen sich neben dem einheitlichen Applikationsinterface noch weitere Vorteile. Hält sich ein Gerätetreiber an die festgelegten Konventionen zur Treiberprogrammierung, ist der Betriebssystemkern in der Lage, die Ressourcen zu verwalten. Er stellt damit sicher, dass die Ressourcen – wie Speicher, Portadressen, Interrupts oder DMA-Kanäle – nur einmal verwendet werden. Der Betriebssystemkern kann darüber hinaus ein Gerät in einen definierten, sicheren Zustand überführen, falls eine zugreifende Applikation beispielsweise durch einen Programmierfehler abstürzt.

Reale und virtuelle Geräte

Treiber benötigt man jedoch nicht nur, wenn es um den Zugriff auf reale Geräte geht. Unter Umständen ist auch die Konzeption sogenannter virtueller Geräte sinnvoll. So gibt es in einem Unix-System das Gerät /dev/zero, das beim lesenden Zugriff Nullen zurückgibt. Mit Hilfe dieses Gerätes lassen sich sehr einfach leere Dateien erzeugen. Auf das Gerät /dev/null können beliebige Daten geschrieben werden; sämtliche Daten werden vom zugehörigen Treiber weggeworfen. Dieses Gerät wird beispielsweise verwendet, um Fehlerausgaben von Programmen aus dem Strom sinnvoller Ausgaben zu filtern.

Kernelprogrammierung

Der Linux-Kernel lässt sich aber nicht nur durch Gerätetreiber erweitern. Erweiterungen, die nicht gerätezentriert sind, die vielleicht den Systemzustand überwachen, Daten verschlüsseln oder den zeitkritischen Teil einer Applikation darstellen, sind in vielen Fällen sinnvoll als Kernelcode zu realisieren.

Zur Kernelprogrammierung und zur Erstellung eines Gerätetreibers ist weit mehr als nur das Wissen um Programmierschnittstellen im Kernel notwendig. Man muss sowohl die Möglichkeiten, die das zugrunde liegende Betriebssystem bietet, kennen als auch die prinzipiellen Abläufe innerhalb des Betriebssystemkerns. Eine zusätzliche Erfordernis ist die Vertrautheit mit der Applikationsschnittstelle. Das gesammelte Know-how bildet die Basis für den ersten Schritt vor der eigentlichen Programmierung: die Konzeption.

Ziel dieses Buches ist es damit,

  • den für die Kernel- und Treiberprogrammierung notwendigen theoretischen Unterbau zu legen,

  • die durch Linux zur Verfügung gestellten grundlegenden Funktionalitäten vorzustellen,

  • die für Kernelcode und Gerätetreiber relevanten betriebssysteminternen und applikationsseitigen Schnittstellen zu erläutern,

  • die Vorgehensweise bei Treiberkonzeption und eigentlicher Treiberentwicklung darzustellen und

  • Hinweise für ein gutes Design von Kernelcode zu geben.

Scope

Auch wenn viele der vorgestellten Technologien unabhängig vom Betriebssystem bzw. von der Linux-Kernel-Version sind, beziehen sich die Beispiele und Übungen auf den Linux-Kernel 4.x.

Ubuntu und Kernel 4.0.3
UP und SMP

Die Beispiele sind auf einem Ubuntu-Linux (Ubuntu 14.04) und dem Kernel 4.0.3 beziehungsweise einem Raspberry Pi 2 unter dem Betriebssystem Raspbian in der Version 2015.03 und dem Kernel in Version 4.0.3 getestet worden. Welche Distribution, ob Debian (pur, in der Ubuntu- oder Raspbian-Variante), Arch Linux, Fedora, SuSE, Red Hat oder ein Selbstbau-Linux (beispielsweise auf Basis von Buildroot), dabei zum Einsatz kommt, spielt im Grunde aber keine Rolle. Kernelcode ist abhängig von der Version des Betriebssystemkerns, nicht aber direkt abhängig von der verwendeten Distribution (Betriebssystemversion). Das Gleiche gilt bezüglich des Einsatzfeldes. Dank seiner hohen Skalierbarkeit ist Linux das erste Betriebssystem, das in eingebetteten Systemen, in Servern, auf Desktop-Rechnern oder sogar auf der Mainframe läuft. Die vorliegende Einführung deckt prinzipiell alle Einsatzfelder ab. Dabei spielt es keine Rolle, ob es sich um eine Einprozessormaschine (Uniprocessor System, UP) oder um eine Mehrprozessormaschine (Symmetric Multiprocessing, SMP) handelt.

Aufbau des Buches

Zu einer systematischen Einführung in die Treiberprogrammierung gehört ein solider theoretischer Unterbau. Dieser soll im folgenden Kapitel gelegt werden. Wer bereits gute Betriebssystemkenntnisse hat und für wen Begriffe wie Prozesskontext und Interrupt-Level keine Fremdwörter sind, kann diesen Abschnitt überspringen. Im Anschluss werden die Werkzeuge und Technologien vorgestellt, die zur Entwicklung von Treibern notwendig sind. In der vierten Auflage wurde dieses Kapitel um einen Abschnitt über die Cross-Entwicklung ergänzt.

Bevor mit der Beschreibung des Treiberinterface im Betriebssystemkern begonnen werden kann, muss das Applikationsinterface zum Treiber hin vorgestellt werden. Denn was nützt es, einen Gerätetreiber zu schreiben, wenn man nicht im Detail weiß, wie die Applikation später auf den Treiber zugreift? Immerhin muss die von der Applikation geforderte Funktionalität im Treiber realisiert werden.

Das folgende Kapitel beschäftigt sich schließlich mit der Treiberentwicklung als solcher. Hier werden insbesondere die Funktionen eines Treibers behandelt, die durch die Applikation aufgerufen werden. In diesem Abschnitt finden Sie auch ein universell einsetzbares Treibertemplate.

Darauf aufbauend werden die Komponenten eines Treibers behandelt, die unabhängig (asynchron) von einer Applikation im Kernel ablaufen. Stichworte hier: Interrupts, Softirqs, Tasklets, Kernel-Threads oder auch Workqueues. Ergänzend finden Sie hier das notwendige Know-how zum Sichern kritischer Abschnitte, zum Umgang mit Zeiten und zur effizienten Speicherverwaltung.

Mit diesen Kenntnissen können bereits komplexere Treiber erstellt werden, Treiber, die sich jetzt noch harmonisch in das gesamte Betriebssystem einfügen sollten. Diese Integration des Treibers ist folglich Thema eines weiteren Kapitels.

Neben den bisher behandelten Treibern für zeichenorientierte Geräte (Character Devices) werden für die Kernelprogrammierung relevante Subsysteme wie GPIO, I2C, USB, Netzwerk und Blockgeräte vorgestellt. Hier zeigen wir Ihnen auch, wie Sie im Kernel existierende und eigene Verschlüsselungsverfahren verwenden.

Einen Treiber zu entwickeln, ist die eine Sache, gutes Treiberdesign eine andere. Dies ist Thema des letzten Kapitels.

Im Anhang schließlich finden sich Hinweise zur Generierung und Installation des Kernels für die PC-Plattform und für den Raspberry Pi. Die Referenzliste der wichtigsten Funktionen, die im Kontext der...

Erscheint lt. Verlag 11.11.2015
Verlagsort Heidelberg
Sprache deutsch
Themenwelt Mathematik / Informatik Informatik Betriebssysteme / Server
Schlagworte Betriebssysteme • Device Tree • Echtzeit • Eingebettete Systeme • Embedded Linux • Embedded Systems • GPIO • Hardware • I2C • Kernel • Kernelprogrammierung • Linux-Kernel • Raspberry Pi • Realtime Linux • SPI • Systemprogrammierung
ISBN-10 3-86491-756-5 / 3864917565
ISBN-13 978-3-86491-756-1 / 9783864917561
Haben Sie eine Frage zum Produkt?
PDFPDF (Wasserzeichen)
Größe: 6,5 MB

DRM: Digitales Wasserzeichen
Dieses eBook enthält ein digitales Wasser­zeichen und ist damit für Sie persona­lisiert. Bei einer missbräuch­lichen Weiter­gabe des eBooks an Dritte ist eine Rück­ver­folgung an die Quelle möglich.

Dateiformat: PDF (Portable Document Format)
Mit einem festen Seiten­layout eignet sich die PDF besonders für Fach­bücher mit Spalten, Tabellen und Abbild­ungen. Eine PDF kann auf fast allen Geräten ange­zeigt werden, ist aber für kleine Displays (Smart­phone, eReader) nur einge­schränkt geeignet.

Systemvoraussetzungen:
PC/Mac: Mit einem PC oder Mac können Sie dieses eBook lesen. Sie benötigen dafür einen PDF-Viewer - z.B. den Adobe Reader oder Adobe Digital Editions.
eReader: Dieses eBook kann mit (fast) allen eBook-Readern gelesen werden. Mit dem amazon-Kindle ist es aber nicht kompatibel.
Smartphone/Tablet: Egal ob Apple oder Android, dieses eBook können Sie lesen. Sie benötigen dafür einen PDF-Viewer - z.B. die kostenlose Adobe Digital Editions-App.

Zusätzliches Feature: Online Lesen
Dieses eBook können Sie zusätzlich zum Download auch online im Webbrowser lesen.

Buying eBooks from abroad
For tax law reasons we can sell eBooks just within Germany and Switzerland. Regrettably we cannot fulfill eBook-orders from other countries.

EPUBEPUB (Wasserzeichen)
Größe: 23,2 MB

DRM: Digitales Wasserzeichen
Dieses eBook enthält ein digitales Wasser­zeichen und ist damit für Sie persona­lisiert. Bei einer missbräuch­lichen Weiter­gabe des eBooks an Dritte ist eine Rück­ver­folgung an die Quelle möglich.

Dateiformat: EPUB (Electronic Publication)
EPUB ist ein offener Standard für eBooks und eignet sich besonders zur Darstellung von Belle­tristik und Sach­büchern. Der Fließ­text wird dynamisch an die Display- und Schrift­größe ange­passt. Auch für mobile Lese­geräte ist EPUB daher gut geeignet.

Systemvoraussetzungen:
PC/Mac: Mit einem PC oder Mac können Sie dieses eBook lesen. Sie benötigen dafür die kostenlose Software Adobe Digital Editions.
eReader: Dieses eBook kann mit (fast) allen eBook-Readern gelesen werden. Mit dem amazon-Kindle ist es aber nicht kompatibel.
Smartphone/Tablet: Egal ob Apple oder Android, dieses eBook können Sie lesen. Sie benötigen dafür eine kostenlose App.
Geräteliste und zusätzliche Hinweise

Zusätzliches Feature: Online Lesen
Dieses eBook können Sie zusätzlich zum Download auch online im Webbrowser lesen.

Buying eBooks from abroad
For tax law reasons we can sell eBooks just within Germany and Switzerland. Regrettably we cannot fulfill eBook-orders from other countries.

Mehr entdecken
aus dem Bereich
Das Praxisbuch für Administratoren und DevOps-Teams

von Axel Miesen

eBook Download (2022)
Rheinwerk Computing (Verlag)
39,90