Michael Beck, Harald Böhme, Mirko Dziadzka, Ulrich Kunitz, Robert Magnus & Dirk Verworner Linux-Kernel- Programmierung Algorithmen und Strukturen der Version 2.0 4., aktualisierte und erweiterte Auflage ADDISON-WESLEY An imprint of Addison Wesley Longman, Inc. Bonn Reading, Massachusetts Menlo Park, California New York Harlow, England Don Mills, Ontario Sydney Mexico City Madrid Amsterdam
Inhaltsverzeichnis Vorwort zur 4., aktualisierten und erweiterten Auflage Vorwort zur 3., überarbeiteten Auflage Vorwort zur 2., korrigierten Auflage Vorwort der Autoren zur 1. Auflage Vorwort von Linus Torvalds zur 1. Auflage xi xi xii xiii xv 1 Linux - Das Betriebssystem 1 1.1 Wesentliche Eigenschaften 3 1.2 Linux-Distributionen 5 2 Die Übersetzung des Kerns 7 2.1 Wo finde ich was? 7 2.2 Die Übersetzung 10 2.3 Zusätzliche Konfigurationsmöglichkeiten 12 3 Einführung in den Kern 15 3.1 Wichtige Datenstrukturen 19 3.1.1 Die Taskstruktur 20 3.1.2 Die Prozeßtabelle 28 3.1.3 Files und Inodes 29 3.1.4 Dynamische Speicherverwaltung 31 3.1.5 Warteschlangen und Semaphore 32 3.1.6 Systemzeit und Zeitgeber (Timer) 34 3.2 Zentrale Algorithmen 35 3.2.1 Signale 35 3.2.2 Interrupts 36 3.2.3 Booten des Systems 38 3.2.4 Timerinterrupt 41 3.2.5 Scheduler 44 3.3 Implementierung von Systemrufen 48 3.3.1 Wie funktionieren Systemrufe eigentlich? 48 3.3.2 Beispiele für einfache Systemrufe 50
3.3.3 Beispiele für komplexere Systemrufe 52 3.3.4 Implementierung eines neuen Systemrufes 61 4 Die Speicherverwaltung 65 4.1 Das architekturunabhängige Speichermodell 67 4.1.1 Speicherseiten 67 4.1.2 Virtueller Adreßraum 67 4.1.3 Übersetzung der linearen Adresse 68 4.1.4 Das Pagedirectory 69 4.1.5 Das mittlere Pagedirectory 70 4.1.6 Die Pagetabelle 71 4.2 Der virtuelle Adreßraum eines Prozesses 74 4.2.1 Das Nutzersegment 74 4.2.2 Virtuelle Speicherbereiche 75 4.2.3 Der Systemruf brk 80 4.2.4 Funktionen für das Mapping 80 4.2.5 Das Kernelsegment 81 4.2.6 Statische Speicherreservierung im Kernelsegment 82 4.2.7 Dynamische Speicherreservierung im Kernelsegment... 83 4.3 Das Caching der Blockgeräte 86 4.3.1 Blockpuffer 87 4.3.2 Update und Bdflush 89 4.3.3 Die Listenstrukturen des Puffercaches 90 4.3.4 Verwendung des Puffercaches 91 4.4 Paging unter Linux 93 4.4.1 Speicherseitenverwaltung und -cache 96 4.4.2 Speicherseitenreservierung 97 4.4.3 Seitenfehler und das Zurückladen einer Speicherseite... 102 5 Interprozeßkommunikation 105 5.1 Synchronisation im Kern 107 5.2 Kommunikation über Dateien 111 5.2.1 Das Sperren ganzer Dateien 111 5.2.2 Sperren von Dateibereichen 113 5.3 Pipes 116 5.4 Debugging mit ptrace 118 5.5 System VIPC 122 5.5.1 Zugriffsrechte, Nummern und Schlüssel 122 5.5.2 Semaphore 123 5.5.3 Messagequeues 127 5.5.4 Shared Memory 130 5.5.5 Die Befehle ipcs und ipcrm 134 5.6 IPC mit Sockets 136 5.6.1 Ein einfaches Beispiel 136 5.6.2 Die Implementierung von Unix-Domain-Sockets 140
vii 6 Das LlNUX-Dateisystem 147 6.1 Grundlagen 148 6.2 Die Repräsentation von Dateisystemen im Kern 151 6.2.1 DasMounten 152 6.2.2 Superblockoperationen 154 6.2.3 Dielnode 157 6.2.4 Inode-Operationen 159 6.2.5 Die File-Struktur 163 6.2.6 File-Operationen 164 6.2.7 Das Offnen einer Datei 167 6.2.8 Der Verzeichniscache 169 6.3 Das Proc-Dateisystem 171 6.4 Das Ext2-Dateisystem 176 6.4.1 Der Aufbau des Ext2-Dateisystems 177 6.4.2 Verzeichnisse im Extl -Dateisystem 179 6.4.3 Blockallokation im Extl -Dateisystem 180 6.4.4 Erweiterungen des Ex 2-Dateisystems 181 7 Gerätetreiber unter Linux 185 7.1 Zeichen- und Blockgeräte 187 7.2 Polling- und Interruptbetrieb 189 7.2.1 Polling 189 7.2.2 Interruptbetrieb 190 7.2.3 Interrupt Sharing 192 7.2.4 Bottom Halfs - Die unteren Interrupthälften 193 7.2.5 Task Queues 195 7.2.6 DMA-Betrieb 197 7.3 Die Hardware, 198 7.3.1 Hardwareerkennung 202 7.3.2 Automatische Interrupterkennung 204 7.4 Die Implementierung eines Treibers 206 7.4.1 Die Setup-Funktion 207 7.4.2 Init 208 7.4.3 Open und Release 210 7.4.4 Read und Write 212 7.4.5 IOCTL 215 7.4.6 Select 217 7.4.7 Lseek 219 7.4.8 MMap 219 7.4.9 Readdir, Fsync und Fasync 219 7.4.10 Check_media_change und Revalidate 219 7.5 Ein Beispiel für den DMA-Betrieb 219 8 Netzwerkimplementierung 225 8.1 Einführung und Überblick 226
Vlll INHALTSVERZEICHNIS 8.1.1 Das Schichtenmodell der Netzwerkimplementation 227 8.1.2 Die Reise der Daten 228 8.2 Wichtige Strukturen 233 8.2.1 Die socket-struktur 233 8.2.2 Die Struktur sk_buff-pufferverwaltung im Netzwerk.. 234 8.2.3 Der INET-Socket - spezieller Teil eines Sockets 237 8.2.4 Protokolloperationen in der proto-struktur 240 8.2.5 Die allgemeine Struktur einer Socketadresse 243 8.3 Netzwerkgeräte unter Linux 244 8.3.1 Ethernet 250 8.3.2 SLIP und PLIP 251 8.3.3 Das Loopback-Gerät 252 8.3.4 Das Dummy-Gerät 252 8.4 ARP - Address Resolution Protocol 252 8.5 IP 255 8.5.1 Allgemeines über IP 255 8.5.2 Funktionen des IP 256 8.5.3 Routing 260 8.5.4 Das IP-Multicasting und IGPM 262 8.5.5 IP-Paketfilter 264 8.5.6 Das IP-Accounting und IP-Firewalling 265 8.6 UDP 266 8.6.1 Funktionen des UDP 266 8.6.2 Weitere Funktionen 268 8.7 TCP 268 8.7.1 Allgemeines zum TCP 268 8.7.2 Der TCP-Kommunikationsendpunkt 269 8.7.3 Funktionen des TCP 270 8.8 Die Paketschnittstelle - eine Alternative? 274 9 Module und Debugging 277 9.1 Was sind Module? 277 9.2 Implementierung im Kernel 278 9.2.1 Signatur von Symbolen 281 9.3 Was kann als Modul implementiert werden? 281 9.4 Parameterübergabe 282 9.5 Der Kern-Dämon 284 9.6 Ein Beispielmodul 285 9.7 Debugging 287 9.7.1 Änderungen sind der Anfang vom Ende 287 9.7.2 Der beste Debugger-printk() 288 9.7.3 Debuggen mit GDB 289 10 Multiprocessing 291 10.1 Die Intel-Mehrprozessorspezifikation 291
ix 10.2 Probleme bei Mehrprozessorsystemen 293 10.3 Änderungen am Kern 294 10.3.1 Initialisierung des Kerns 294 10.3.2 Scheduling 295 10.3.3 Nachrichtenaustausch der Prozessoren 296 10.3.4 Eintritt in den Kern-Modus 296 10.3.5 Interruptbehandlung 297 10.4 LINUX-SMP compilieren 297 A Systemrufe 299 A.l Die Prozeßverwaltung 301 A.2 Das Dateisystem 337 A.3 Die Kommunikation 366 A.4 Die Speicherverwaltung 369 A.5 Die Initialisierung 374 A.6 Und der ganze Rest 376 B Kernnahe Kommandos 377 B.l free - Übersicht über den Systemspeicher 377 B.2 ps - Ausgabe der Prozeßstatistik 378 B.3 Nachträgliche Kernkonfiguration 384 B.4 top - Die CPU-Charts 385 B.5 Init - Primus inter pares 387 B.6 shutdown - Das Herunterfahren des Systems 393 B.7 strace - Observierung eines Prozesses 394 B.8 Konfiguration des Netzwerk-Interfaces 398 B.9 traceroute - Der Ariadnefaden im Internet 399 B.10 Konfiguration einer seriellen Schnittstelle 401 B.ll Konfiguration einer parallelen Schnittstelle 404 B.12 Wir basteln uns einen Verzeichnisbaum 406 C Das Proc-Dateisystem 415 C.l Das Verzeichnis /proc/ 416 C.2 Das Verzeichnis net/ 421 C.3 Das Verzeichnis seif/ 422 C.4 Das Verzeichnis sys/ 426 D Der Boot-Prozeß 427 D.l Ablauf des Bootens 427 D.2 LILO - der Linux-Lader 429 D.2.1 MS-DOS-MBR startet LILO 429 D.2.2 LILO wird von einem Bootmanager gestartet 430 D.2.3 LILO im Master-Boot-Record 431 D.2.4 LILO-Dateien 431 D.2.5 LILO-Bootparameter 435
D.2.6 LILO-Startmeldungen 438 D.2.7 Fehlermeldungen 438 E Nützliche Kernfunktionen 441 L Literaturverzeichnis 455 I Index 460