Linux (Kernel)

Unix-ähnlicher, monolithischer Betriebssystem-Kernel, Basis aller Linux-Betriebssysteme / Linux-Distributionen
Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 15. Mai 2005 um 00:51 Uhr durch 84.179.243.191 (Diskussion) (Portierbarkeit). Sie kann sich erheblich von der aktuellen Version unterscheiden.

Linux im eigentlichen Sinne ist „nur“ ein Betriebssytemkern (engl. Kernel), der in verschiedenen Betriebssystemen zum Einsatz kommt. Dieser Artikel beschreibt diesen Linux-Kernel. Der Begriff Linux wird jedoch auch für mehr als nur den Betriebssystemkern verwendet, siehe dazu Linux. Linux wurde ursprünglich 1991 vom Finnen Linus Torvalds, von dem die Entwicklung auch heute noch koordiniert wird, für die x86-Architektur geschrieben. Er steht unter der freien GPL-Lizenz. Inzwischen ist Linux auch eine auf ihn eingetragene notorisch bekannte Marke (Warenzeichen).

Tux, der Linux-Pinguin

Lizenz

Making Linux GPL'd was definitely the best thing I ever did.Linus Torvalds

Torvalds gab Linux ursprünglich unter einer Lizenz heraus, die jede kommerzielle Nutzung verbot. Diese Lizenz tauschte er bald gegen die GNU General Public License (Version 2). Sie erlaubt die Verteilung und sogar den Verkauf von (auch veränderten) Versionen von Linux. Die Bedingungen hierfür sind, dass alle Kopien auch unter der selben Lizenz stehen müssen und der Quelltext immer verfügbar gemacht werden muss.

Die bei GPL-Software übliche Klausel, daß statt der Version 2 der GNU General Public License auch eine neuere Version verwendet werden kann, fehlt jedoch beim Linux-Kernel. Die Entscheidung, ob eine absehbare Version 3 der GNU General Public License für den Linux-Kernel verwendet wird, ist damit prinzipiell nur mit Zustimmung aller Entwickler möglich.

Namensherkunft

Eigentlich sollte Linux nach dem Willen von Linus Torvalds Freax heißen, eine Wortschöpfung aus Freak (Verrückter, aber auch jemand, der sich für etwas begeistert), Free für Freie Software und dem oftmals üblichen x in Anspielung auf die Ähnlichkeit zu Unix.

Ganz am Anfang der Programmierung des Betriebssystems hatte Torvalds etwa ein halbes Jahr lang die Dateien unter Freax abgelegt. Auch den Namen Linux hatte sich Torvalds bereits überlegt, er erschien ihm aber zu egoistisch. Um anderen Leuten die Möglichkeit zu geben, am Betriebssystem mitzuarbeiten oder Verbesserungsvorschläge zu machen, sollten die Dateien auf dem FTP-Server (ftp.funet.fi) der Universität Helsinki abgelegt werden. Das war etwa im September 1991. Der damalige Verantwortliche für den Server hieß Ari Lemmke (Mitarbeiter der Universität). Lemmke war mit dem Namen Freax nicht einverstanden, er bevorzugte den Arbeitsnamen Linux. Ohne mit Torvalds darüber zu diskutieren, nannte er den Bereich am Server einfach Linux, was Torvalds schließlich akzeptierte, um große Diskussionen zu vermeiden und auch, wie Torvalds zugibt, weil Linux einfach der bessere Name war. So setzte sich der eigentlich gar nicht geplante Name Linux weltweit durch.

Entwicklungsprozess

Die Entwicklung von Linux liegt durch die freie GPL-Lizenz nicht in der Hand von Einzelpersonen, Konzernen oder Ländern, sondern sie ist das weltweite Gemeinschaftswerk vieler Programmierer, die sich unter anderem über das Internet austauschen. Für diesen Zweck existieren viele Foren und Gruppen, in denen für jedermann die Möglichkeit besteht, Probleme oder Verbesserungsvorschläge einzureichen. Durch diese unkomplizierte Vorgehensweise ist eine schnelle und stetige Entwicklung gewährleistet: Bei kaum einem anderen System werden derart schnell und effizient Fehler beseitigt und behoben. Allerdings liegt die Kontrolle über die Arbeit am Kernel weiterhin bei Linus Torvalds und einigen speziell ausgesuchten Programmierern.

Als Reaktion auf den Rechtsprozess mit SCO ist die Einführung eines „Linux Developer's Certificate of Origin“ von Linus Torvalds und Andrew Morton bekannt gegeben worden. Diese Änderung liegt an der Unmöglichkeit nach dem bisherigen Modell des Linux-Entwicklungsprozesses die Herkunft einer Erweiterung oder Verbesserung des Kernels nachvollziehen zu können.

These days, most of the patches in the kernel don't actually get sent directly to me. That not just wouldn't scale, but the fact is, there's a lot of subsystems I have no clue about, and thus no way of judging how good the patch is. So I end up seeing mostly the maintainers of the subsystem, and when a bug happens, what I want to see is the maintainer name, not a random developer who I don't even know if he is active any more. So at least for me, the _chain_ is actually mostly more important than the actual originator. There is also another issue, namely the fact that when I (or anybody else, for that matter) get an emailed patch, the only thing I can see directly is the sender information, and that's the part I trust. When Andrew sends me a patch, I trust it because it comes from him - even if the original author may be somebody I don't know. So the _path_ the patch came in through actually documents that chain of trust - we all tend to know the "next hop", but we do _not_ necessarily have direct knowledge of the full chain. So what I'm suggesting is that we start "signing off" on patches, to show the path it has come through, and to document that chain of trust. It also allows middle parties to edit the patch without somehow "losing" their names - quite often the patch that reaches the final kernel is not exactly the same as the original one, as it has gone through a few layers of people. (Linus Torvalds, zitiert aus einem Interview [1])

Zur deutlichen Unterscheidung von freigegebenen Kernelversionen und Entwicklerkerneln werden erstere nach dem Punkt mit einer geraden Ziffer und letztere mit einer ungeraden gekennzeichnet. Dadurch, dass Programmierer weltweit an der Entwicklung arbeiten, wird Linux praktisch 24 Stunden am Tag weiterentwickelt. Weil Menschen aus der ganzen Welt aus verschiedenen Kulturen aus unterschiedlichen Wissensgebieten daran arbeiten, ist dieses Betriebssystem so universell einsetzbar.

Linux-Versionen

Auf der Website Kernel.org werden alle alten und neuen Kernel-Versionen archiviert. Die Versionen des Linux-Kernels folgen einem bestimmten Schema:

Die erste Ziffer wird nur bei grundlegenden Änderungen in der Systemarchitektur angehoben. Während der Entwicklung des 2.5er Kernels kam die Diskussion unter den Kernel-Programmierern auf, wegen der relativ grundlegenden Änderungen verglichen mit dem 2.4er Kernel, den nächsten Produktionskernel als 3.0 zu bezeichnen, Linus war aber aus verschiedenen Gründen dagegen, sodass der resultierende Kernel als 2.6 bezeichnet wurde.

Die zweite Ziffer gibt das jeweilige „Majorrelease“ an. Stabile Versionen (sog. Produktionskernel) werden von den Entwicklern stets durch gerade Ziffern wie 2.2, 2.4 und 2.6 gekennzeichnet, während die Testversionen (sog. Entwicklerkernel) immer ungerade Ziffern tragen: 2.3, 2.5 und 2.7.

Zusätzlich bezeichnet eine dritte Zahl das „Minorrelease“. Beim stabilen Zweig werden hier normalerweise nur Fehlerbereinigungen und Sicherheitsupdates zugelassen. Der Kernel wird damit zum Beispiel mit einer Versionsnummer wie 2.6.7 (Produktionskernel) oder 2.5.75 (Entwicklerkernel) bestimmt.

Um die Korrektur eines schwerwiegenden NFS-Fehler schneller verbreiten zu können, wurde mit der Version 2.6.8.1 erstmals eine vierte Ziffer eingeführt. Seit März 2005 (Kernel 2.6.11) wird diese Nummerierung offizell verwendet. So ist es möglich die Stabilität des Kernels trotz schneller Veröffentlichungszyklen zu gewährleisten und Korrekturen von kritischen Fehlern innerhalb von wenigen Stunden in den offiziellen Kernel zu übernehmen - wobei sich die vierte Ziffer erhöht (z.B. von 2.6.11.1 auf 2.6.11.2). Die Minorreleasenummer, also die dritte Ziffer, wird hingegen nur bei Einführung neuer Funktionen hochgezählt.

Pflege der Kernel-Versionen

Während Torvalds die neuesten Entwicklungsversionen veröffentlicht, wurde die Pflege der älteren „stabilen“ Versionen an andere Programmierer abgegeben. Gegenwärtig ist David Weinehall für die 2.0er Serie verantwortlich, Marc-Christian Petersen für den Kernel 2.2, Marcelo Tosatti für den Kernel 2.4 und Andrew Morton für den aktuellen stabilen Kernel 2.6. Zusätzlich zu diesen offiziellen und über Kernel.org oder einen seiner Mirrors zu beziehenden Kernel-Quellcodes kann man auch alternative „Kernel-Trees“ aus anderen Quellen benutzen. Distributoren von Linux-basierten Betriebssystemen pflegen meistens ihre eigenen Versionen des Kernels und beschäftigen zu diesem Zwecke fest angestellte Kernel-Hacker, die ihre Änderungen meist auch in die offiziellen Kernels einfließen lassen. Distributions-Kernel sind häufig intensiv gepatcht, um auch Treiber zu beinhalten, die noch nicht im offiziellen Kernel sind, von denen der Distributor aber glaubt, dass seine Kundschaft sie benötigen könnte und die notwendige Stabilität resp. Fehlerfreiheit dennoch gewährleistet ist.

Die aktuelle stabile Kernelserie (2.6) wurde im Dezember 2003 veröffentlicht. Es wird in nächster Zeit keine neue Entwickler-Version geben, weil der stabile Kernel und der Entwicklerkernel (der sogenannte mm-Kernel) jetzt mit einer gemeinsamen Codebasis (Linux 2.6) entwickelt werden. Es ist aber möglich, dass der Entwicklerkernel und der stabile Kernel in Zukunft wieder getrennte Wege gehen, falls fundamentale Änderungen nötig werden sollten. Die stabile Version ist auf folgende Art und Weise vom Entwicklerkernel zu unterscheiden: Die stabile Version hat immer eine gerade Versionsunternummer, also momentan 2.6, die Entwicklerversion eine ungerade. Die nächste Entwicklerversion würde also mit 2.7 bezeichnet, die darauf aufbauende stabile Version 2.8.

Erscheinungstermine

17. September 1991 Initial Public Release v0.01
5. Oktober 1991 Erster „offizieller“ Kernel v0.02
16. April 1994 v1.0
9. Juni 1996 v2.0
21. Januar 1999 v2.2.0
4. Januar 2001 v2.4.0
18. Dezember 2003 v2.6.0

Technologie

Aufgaben des Kernels

Der Kernel bildet die hardwareabstrahierende Schicht, d.h. er stellt der auf dieser Basis aufsetzenden Software eine einheitliche Schnittstelle (API), unabhängig von der Hardwarearchitektur, zur Verfügung. Er ist ein modularer monolithischer Betriebssystemkern und ist zuständig für Speicherverwaltung, Prozessverwaltung, Multitasking, Lastverteilung, Sicherheitserzwingung und Eingabe/Ausgabe-Operationen auf verschiedenen Geräten.

Funktionsweise

Bei einem strikt monolithischen Kernel wird der gesamte Quellcode inklusive aller Treiber in das Kernel-Image (den ausführbaren Kernel) kompiliert. Der Linux-Kernel benutzt deshalb Module, die während des Betriebs geladen und wieder entfernt werden können. Damit wird die Flexibilität erreicht, um unterschiedlichste Hardware ansprechen zu können, ohne sämtliche (auch nicht benötigte) Treiber und andere Systemteile im Speicher halten zu müssen.

Sind Teile der Hardwarespezifikationen nicht genügend offengelegt, so stützt sich Linux notfalls über spezielle VM86-Modi auch auf das BIOS des Systems, u.a. auf die Erweiterungen gemäß den Standards APM, ACPI und VESA. Um unter diesen Voraussetzungen x86-kompatible Hardware z.B. auf der DEC-Alpha-Platform zu betreiben, werden teilweise sogar Emulatoren zur Ausführung entsprechenden ROM-Codes verwendet. Linux selbst übernimmt das System beim Bootprozess typischerweise in dem Moment, wo der BIOS-Bootloader erfolgreich war und alle Systeminitialisierungen des BIOS abgeschlossen sind.

Der Linux-Kernel ist fast komplett in der Programmiersprache C geschrieben, wobei einige GNU-C-Erweiterungen benutzt werden. Eine Ausnahme bilden die architekturabhängigen Teile des Codes (im Verzeichnis arch innerhalb der Linux-Sourcen), wie z.B. der Beginn des Bootvorganges, die in Assemblersprache geschrieben sind.

Der Kernel ist ein Betriebssystemkern und kein Betriebssystem im landläufigen Sinne, da er ohne weitere Programme relativ nutzlos ist.

Siehe auch: Gerätenamen unter Linux, Network Block Device

Architektur

Linux ist heute ein hybrid monolithischer Kernel. Dies bedeutet, dass man den größten Teil der Treiber, die nicht während der ersten Startphase (bevor ein Dateisystem eingebunden ist) benötigt werden, als Module konfigurieren kann, die dann dynamisch nachgeladen oder auch während des Betriebs entladen werden können, wenn ihre Funktionalität nicht mehr benötigt wird. Die Treiber im Kernel und die Kernel-Module laufen im Priviligierten Modus (x86: Ring 0), haben also unbeschränkten Zugriff auf die Hardware. Einige wenige Module des Kernels laufen im eingeschränkten Benutzermodus (x86: Ring 3). Die Level 1 und 2 der x86-Architektur werden vom Linux-Kernel nicht genutzt.

Die Tatsache, dass Linux nicht auf einem Mikrokernel basiert, war Thema eines berühmten Flame Wars zwischen Linus Torvalds und Andrew S. Tanenbaum. Anfang der 1990er Jahre, als Linux entwickelt wurde, galten monolithische Kernels als obsolet (Linux war zu diesem Zeitpunkt noch rein monolithisch, die Möglichkeit, auch Module verwenden zu können, wurde erst später nachgerüstet). Die Diskussion und Zusammenfassungen derselben können an verchiedenen Stellen des Internets gefunden werden.

Portierbarkeit

Obwohl Linus Torvalds eigentlich nicht beabsichtigt hatte, einen portierbaren Kernel zu schreiben, hat sich Linux dank des GNU Compilers GCC doch in diese Richtung entwickelt. Es ist inzwischen mit eines der am häufigsten portierten Systeme (nur noch NetBSD läuft auf etwa gleich vielen Architekturen). Das Repertoire reicht dabei von eher exotischen Betriebsumgebungen wie dem iPAQ-Handheld-Computer oder gar Digitalkameras bis hin zu Großrechnern wie IBMs zSeries.

Obwohl die Portierung auf die S/390 ursprünglich ein vom IBM-Management nicht genehmigtes Unterfangen war (siehe auch: Skunk Works), hat Big Blue wohl inzwischen Gefallen am Linux-System gefunden, und so soll auch die nächste IBM-Supercomputergeneration Blue Gene mit einem eigenen Linux-Port ausgestattet werden, sobald sie fertig ist.

Ursprünglich hatte Torvalds eine ganz andere Art von Portierbarkeit für sein System angestrebt, nämlich die Möglichkeit freie GPL- und andere quelloffene Software leicht unter Linux kompilieren zu können. Dieses Ziel wurde bereits sehr früh erreicht und macht sicherlich einen guten Teil des Erfolges von Linux aus, da es jedermann eine einfache Möglichkeit bietet, auf einem freien System freie Software laufen zu lassen.

Linux läuft gegenwärtig auf den folgenden Architekturen:

User Mode Linux

Ein besonderer Port ist das User Mode Linux (UML). Prinzipiell handelt es sich dabei um einen Port des Linux-Kernels auf sein eigenes Systemcall-Interface. Dies ermöglicht es, einen Linux-Kernel als normalen Prozess auf einem laufenden Linux-System zu starten. Der User-Mode-Kernel greift dann nicht selbst auf die Hardware zu, sondern reicht entsprechende Anforderungen an den echten Kernel durch. Durch diese Konstellation werden „Sandkästen“ ähnlich den Virtual Machines von Java oder den Jails von FreeBSD möglich, in denen ein normaler Benutzer Root-Rechte haben kann, ohne dem tatsächlichen System schaden zu können.

µCLinux

µCLinux ist eine Linux-Variante für Computer ohne Memory Management Unit (MMU) und kommt vorwiegend auf Microcontrollern und Embedded Devices zum Einsatz. Seit Linux-Version 2.6 ist µCLinux Teil des Linux-Projektes.

Neuerungen im Kernel 2.6

Der aktuelle stabile Kernel wurde ab Dezember 2001 auf Basis des damaligen 2.4er Kernels entwickelt und weist eine Reihe von Neuerungen auf.

Die wohl offensichtlichste Änderung gegenüber Version 2.4 zeigt sich, wenn man zum ersten Mal eine grafische Oberfläche auf dem neuen Kernel startet: Die X-Oberfläche fühlt sich spürbar „schneller“ und reaktionsfreudiger an, und andere interaktive Anwendungen wie z.B. Soundwiedergabe laufen nun auch unter hoher Last ohne Aussetzer. Dies wurde durch eine Reihe von Maßnahmen erreicht, die im folgenden besprochen werden sollen:

  • Neuer O(1)-Scheduler und verbessertes Thread-Management
  • Prozesse werden nicht mehr alle 1/100 Sekunde, sondern jede 1/1000 Sekunde unterbrochen
  • Der Kernel ist nun voll präemptiv

Der O(1)-Scheduler

In einem Multitasking-fähigen Betriebssystem muss es eine Instanz geben, die den Prozessen, die laufen wollen, Rechenzeit zuteilt und sie nach Ablauf der zugeteilten Zeitspanne (Timeslice) wieder „schlafen legt“. Diese Instanz bildet der sog. Scheduler, den Ingo Molnar für den 2.6er Kernel komplett neu konzipiert und implementiert hat.

Der neue O(1)-Scheduler erhielt seinen Namen, weil die relevanten Algorithmen, auf denen der Scheduler basiert, die Komplexität O(1) haben. Der O(1)-Scheduler arbeitet daher sehr effizient und benötigt für den eigenen Betrieb nur sehr wenig Rechenzeit. Er verwendet prinzipiell zwei verkettete Listen, in denen die Prozesse eingetragen sind, die noch laufen wollen, und diejenigen, die bereits gelaufen sind. Nachdem alle Prozesse in der zweiten Liste stehen, werden die Arrays getauscht, und das Spiel beginnt von neuem. Der Scheduler ist darüber hinaus so ausgelegt, dass Prozesse, die große Mengen Rechenzeit in Anspruch nehmen wollen, gegenüber interaktiven Prozessen benachteiligt werden, wenn beide zur gleichen Zeit laufen wollen. Interaktive Prozesse benötigen meist nur sehr wenig Rechenzeit, sind aber häufig sehr zeitkritisch (so will man z.B. nicht ewig auf eine Reaktion der grafischen Oberfläche warten). Der neue Scheduler besitzt ausgefeilte Algorithmen, um festzustellen, ob ein Prozess interaktiv ist oder die CPU eher lange belegt. Gegenwärtig arbeiten mehrere Kernelprogrammierer noch daran, gewisse Grenzfälle auszubalancieren (ein Prozess wird plötzlich von einem interaktiven zu einem CPU-lastigen und umgekehrt). Der interne „Takt“ des Kernels wurde von 100 Hz auf 1000 Hz erhöht, d.h. die maximale Länge eines Timeslice beträgt nun 1/1000 Sekunde. Auch hiervon profitieren besonders die interaktiven Prozesse, da sie früher „wieder an der Reihe sind“. Eine weitere Stärke des neuen Schedulers liegt im verbesserten Thread-Management und der besseren Unterstützung von symmetrischem Multiprocessing (SMP) und Hyper-Threading. Dies kommt vor allem hoch belasteten Servern zugute. In Testsituationen konnten unter dem neuen Scheduler 100.000 Threads gestartet werden, ohne dass das System subjektiv langsamer wurde. Weiterhin sorgt der neue Scheduler dafür, dass die zur Verfügung stehenden CPUs optimal ausgelastet werden, ohne Prozesse übermäßig oft zwischen zwei CPUs hin- und her wechseln zu lassen.

Präemptiver Kernel

Der Kernel ist ab Version 2.6 in den meisten Funktionen präemptiv, d.h. selbst wenn das System gerade im Kernel-Modus Aufgaben ausführt, kann dieser Vorgang durch einen Prozess aus dem User-Modus unterbrochen werden. Der Kernel macht dann weiter, wenn der Usermodus-Prozess seinen Timeslice aufgebraucht hat. Dies funktioniert bis auf einige Kernel-Funktionen, die atomar (nicht unterbrechbar) ablaufen müssen, sehr gut und kommt ebenfalls der Interaktivität zugute.

Siehe auch: präemptives Multitasking

Weitere wichtige Änderungen

Soweit möglich wurden in Linux 2.6 die Maximalzahl für bestimmte Ressourcen angehoben. Die Anzahl von möglichen Benutzern und Gruppen wurde von 65.000 auf über 4 Milliarden erhöht, ebenso wie die Anzahl der Prozess-IDs (von 32.000 auf 1 Milliarde) und die Anzahl der Geräte (Major/Minor-Nummern). Weitere leistungssteigernde Maßnahmen betrafen die I/O-Scheduler, das Threading mit der neuen Native POSIX Thread Library und den Netzwerk-Stack, der nun ebenfalls in den meisten Tests O(1) skaliert ist.

Literatur

  • Wolfgang Mauerer: Linux Kernelarchitektur, Hanser Fachbuchverlag, November 2003, ISBN 446225668