1 - Inhaltsverzeichnis [Seite 6]
2 - Vorwort [Seite 14]
3 - 1 Einführung und Uberblick [Seite 16]
3.1 - 1.1 Aufgaben des Kerns [Seite 17]
3.2 - 1.2 Implementierungsstrategien [Seite 17]
3.3 - 1.3 Bestandteile des Kernels [Seite 18]
4 - 2 Prozessverwaltung [Seite 34]
4.1 - 2.1 Prozessprioritäten [Seite 35]
4.2 - 2.2 Lebenszyklus eines Prozesses [Seite 37]
4.3 - 2.3 Repräsentation von Prozessen [Seite 40]
4.4 - 2.4 Systemaufrufe zur Prozessverwaltung [Seite 51]
4.5 - 2.5 Implementierung des Schedulers [Seite 67]
4.6 - 2.6 Erweiterungen des Schedulers [Seite 80]
5 - 3 Speicherverwaltung [Seite 86]
5.1 - 3.1 Überblick [Seite 86]
5.2 - 3.2 Organisation nach dem (N)UMA-Modell [Seite 88]
5.3 - 3.3 Seitentabellen [Seite 98]
5.4 - 3.4 Initialisierung der Speicherverwaltung [Seite 105]
5.5 - 3.5 Verwaltung des physikalischen Speichers [Seite 132]
5.6 - 3.6 Der Slab-Allokator [Seite 162]
5.7 - 3.7 Verwaltung des virtuellen Prozessspeichers [Seite 185]
5.8 - 3.8 Prozessorcache- und TLB-Steuerung [Seite 225]
6 - 4 Interprozesskommunikation und Locking [Seite 230]
6.1 - 4.1 Steuerungsmechanismen [Seite 230]
6.2 - 4.2 Locking-Mechanismen des Kerns [Seite 234]
6.3 - 4.3 System V-Interprozesskommunikation [Seite 240]
6.4 - 4.4 Andere IPC-Mechanismen [Seite 253]
7 - 5 Gerätetreiber [Seite 262]
7.1 - 5.1 IO-Architektur [Seite 262]
7.2 - 5.2 Zugriff auf Erweiterungsgeräte [Seite 268]
7.3 - 5.3 Treiberregistrierung [Seite 272]
7.4 - 5.4 Verbindung mit dem Dateisystem [Seite 274]
7.5 - 5.5 Treiberoperationen [Seite 278]
7.6 - 5.6 Ressourcen-Reservierung [Seite 298]
7.7 - 5.7 Bussysteme [Seite 304]
8 - 6 Module [Seite 328]
8.1 - 6.1 Module verwenden [Seite 329]
8.2 - 6.2 Module einfügen und löschen [Seite 336]
8.3 - 6.3 Automatisierung und Hotplugging [Seite 356]
8.4 - 6.4 Versionskontrolle [Seite 359]
9 - 7 Das virtuelle Dateisystem [Seite 366]
9.1 - 7.1 Dateisystemtypen [Seite 367]
9.2 - 7.2 Das Common File Model [Seite 368]
9.3 - 7.3 Aufbau des VFS [Seite 373]
9.4 - 7.4 Arbeiten mit VFS-Objekten [Seite 392]
9.5 - 7.5 Standardfunktionen [Seite 410]
10 - 8 Dateisystemimplementierungen [Seite 416]
10.1 - 8.1 Second Extended Filesystem [Seite 418]
10.2 - 8.2 Third Extended Filesystem [Seite 461]
10.3 - 8.3 Das Dateisystem [Seite 466]
11 - 9 Netzwerke [Seite 506]
11.1 - 9.1 Verkettete Computer [Seite 507]
11.2 - 9.2 ISO/OSI- und TCP/IP-Referenzmodell [Seite 507]
11.3 - 9.3 Kommunikation über Sockets [Seite 511]
11.4 - 9.4 Das Schichtmodell der Netzwerkimplementierung [Seite 519]
11.5 - 9.5 Socketpuffer [Seite 521]
11.6 - 9.6 Datenübertragungsschicht [Seite 524]
11.7 - 9.7 Vermittlungsschicht [Seite 532]
11.8 - 9.8 Transportschicht [Seite 549]
11.9 - 9.9 Anwendungsschicht [Seite 564]
12 - 10 Systemaufrufe [Seite 572]
12.1 - 10.1 Grundlagen der Systemprogrammierung [Seite 572]
12.2 - 10.2 Vorhandene Systemaufrufe [Seite 579]
12.3 - 10.3 Realisierung von Systemaufrufen [Seite 584]
13 - 11 Kernel-Aktivitäten und Zeitfluss [Seite 602]
13.1 - 11.1 Interrupts [Seite 602]
13.2 - 11.2 Software-Interrupts [Seite 621]
13.3 - 11.3 Tasklets und Work Queues [Seite 624]
13.4 - 11.4 Wait Queues und Completions [Seite 627]
13.5 - 11.5 Kerneltimer [Seite 632]
14 - 12 Page- und Buffer-Cache [Seite 644]
14.1 - 12.1 Struktur des Page-Caches [Seite 645]
14.2 - 12.2 Der Buffer-Cache [Seite 648]
14.3 - 12.3 Adressräume [Seite 650]
14.4 - 12.4 Implementierung des Puffer-Caches [Seite 658]
15 - 13 Datensynchronisation [Seite 674]
15.1 - 13.1 pdflush [Seite 675]
15.2 - 13.2 Starten eines neuen Threads [Seite 676]
15.3 - 13.3 Thread-Initialisierung [Seite 676]
15.4 - 13.4 Durchführen der Arbeit [Seite 678]
15.5 - 13.5 Periodisches Zurückschreiben [Seite 679]
15.6 - 13.6 Assoziierte Datenstrukturen [Seite 679]
15.7 - 13.7 Zentrale Steuerung [Seite 682]
15.8 - 13.8 Superblock-Synchronisation [Seite 684]
15.9 - 13.9 Inoden-Synchronisation [Seite 685]
15.10 - 13.10 Verstopfungen [Seite 689]
15.11 - 13.11 Zurückschreiben unter Druck [Seite 692]
15.12 - 13.12 Systemaufrufe zur Synchronisationskontrolle [Seite 694]
15.13 - 13.13 Vollständige Synchronisierung [Seite 694]
15.14 - 13.14 Synchronisieren einzelner Dateien [Seite 696]
15.15 - 13.15 Synchronisieren von Memory Mappings [Seite 698]
16 - 14 Swapping [Seite 700]
16.1 - 14.1 Überblick [Seite 700]
16.2 - 14.2 Swapping im Linux-Kernel [Seite 704]
16.3 - 14.3 Verwaltung von Swap-Bereichen [Seite 708]
16.4 - 14.4 Der Swap-Cache [Seite 718]
16.5 - 14.5 Zurückschreiben der Daten [Seite 730]
16.6 - 14.6 Seitenauswahl - Swap Policy [Seite 731]
16.7 - 14.7 Behandlung von Page Faults [Seite 747]
16.8 - 14.8 Auslösen des Swappings [Seite 751]
16.9 - 14.9 Verkleinern anderer Caches [Seite 756]
17 - Literaturverzeichnis [Seite 760]
18 - Index [Seite 762]
19 - Symbole [Seite 770]
9 Netzwerke (S. 905-906)
Linux ist ein Kind des Internets, darüber besteht kein Zweifel: Seine Entwicklung hat viele verbreitete Ansichten über Projektmanagement bei weltweiten Programmierergruppen ad absurdum geführt, was vor allem der Kommunikation über das Internet zu verdanken war. Seit die ersten Kernelquellen vor mehr als einem Jahrzehnt auf einem ftp-Server im Internet verfügbar gemacht wurden, waren Netzwerke immer das zentrale Rückgrat, wenn es um Datenaustausch, Entwicklung von Konzepten und Code oder die Beseitigung von Fehlern im Kern ging. Die Kernelmailingliste ist ein lebendiges Beispiel dafür, dass sich an dieser Technik bis heute nichts geändert hat: Jeder kann die Beiträge lesen, sich selbst mit seiner Meinung beteiligen und dadurch zur Entwicklung von Linux beitragen – vorausgesetzt, man hat etwas Vernünftiges zu sagen.
Die Beziehung von Linux zu Netzwerken aller Art ist sehr innig, schließlich ist das Internet der Brutkasten, in dem es groß geworden ist. Linux-Rechner machen einen bedeutenden Anteil aller Server aus, die das Internet bilden, weshalb die Netzwerkimplementierung einer der wichtigsten Bestandteile des Kerns ist, dem bei der Entwicklung immer große Beachtung geschenkt wird. Es gibt kaum eine Netzwerkmöglichkeit, die von Linux nicht unterstützt wird. Die Implementierung der Netzwerkfunktionalitäten ist einer der komplexesten und umfangreichsten Teile des Kerns: Neben den klassischen Internet-Protokollen wie TCP, UDP und dem assoziierten Transportmechanismus IP unterstützt Linux viele weitere Möglichkeiten, die die Verbindung von Computern ermöglichen, um die größtmögliche Fähigkeit zur Zusammenarbeit mit allen denkbaren Rechner- und Betriebssystemtypen zu ermöglichen. Auch die Unterstützung einer riesigen Zahl von Hardwaremöglichkeiten zur Datenübertragung – angefangen bei Ethernet- Karten über Token-Ring-Adapter bis hin zu ISDN-Karten und Modems – macht die Aufgabe des Kerns nicht gerade einfacher.
Dennoch konnten die Linux-Entwickler ein erstaunlich gut strukturiertes Modell schaffen, mit dem sich die teilweise recht unterschiedlichen Ansätze vereinigen lassen. Auch wenn dieses Kapitel zu den umfangreichsten im Buch gehört, ist es nicht möglich, jedes Detail der Netzwerkimplementierung zu berücksichtigen. Es ist bereits unmöglich, auf alle Treiber und Protokolle grob einzugehen, da so viele Informationen vorhanden sind, die nicht nur eines, sondern gleich mehrere Bücher füllen würden. Die C-Implementierung des Netzwerklayers belegt – ohne Gerätetreiber für Netzwerkkarten! – bereits 7 MiB in den Kernelquellen, was gedruckt wesentlich mehr als 2500 Seiten ausmacht und ein beeindruckendes Codemassiv ist. Dennoch finden sich viele Konzepte, die hinter diesem Code stehen und das logische R¨uckgrat des Netzwerksubsystems bilden:
Genau diese Punkte werden uns in diesem Kapitel interessieren. Außerdem werden wir uns an der TCP/IP-Implementierung orientieren, da dies die mit Abstand am weitesten verbreiteten Netzwerkprotokolle sind. Natürlich musste die Entwicklung des Netzwerklayers nicht ganz bei Null beginnen: Standards und Konventionen, die den Datenaustausch zwischen Computern ermöglichen, sind bereits seit Jahrzehnten vorhanden und entsprechend gut bekannt und eingeführt. Linux implementiert diese Standards, um die Verbindung mit anderen Computern aufnehmen zu können.
9.1 Verkettete Computer
Die Kommunikation von Computern untereinander ist ein komplexes Thema, das viele Bereiche umfasst, in denen verschiedenste Fragen gelöst werden müssen. Um nur einige zu nennen:
- Wie wird die Verbindung physikalisch hergestellt? Welche Kabel werden verwendet, welche Beschränkungen und speziellen Anforderungen besitzen die Medien?
- Wie werden Übertragungsfehler behandelt?
- Wie werden individuelle Computer in einem Netzwerk identifiziert?
- Wie können Daten zwischen Computern ausgetauscht werden, die nur indirekt verbunden sind, d.h. über einen oder mehrere andere Computer als Zwischenstationen? Wie kann der günstigsteWeg herausgefunden werden?
- Wie werden die Nutzdaten verpackt, um nicht von speziellen Merkmalen einzelner Rechner abhängig zu sein?
- Wie lassen sich mehrere Netzwerkdienste auf einem Rechner identifizieren?
Dieser Katalog lässt sich fast beliebig fortsetzen. Leider ist nicht nur die Anzahl der Fragen, sondern auch die Anzahl der Lösungsmöglichkeiten unbeschränkt, weshalb im Laufe der Zeit sehr viele Vorschläge gemacht wurden, umdie Probleme in den Griff zu bekommen. Als " vernünftig" haben sich dabei vor allem jene Systeme herauskristallisiert, die die Probleme in mehrere Kategorien einteilen und auf diese Weise verschiedene Schichten schaffen, die sich mit der Lösung einer klar definierten Fragestellung beschäftigen und mit den über/untergeordneten Schichten nur über genau festgelegte Mechanismen kommunizieren. Dieser Ansatz erleichtert Implementierung, Wartung und vor allem Fehlersuche drastisch.