Open Source im professionellen Einsatz

Newsletter abonnieren
Seite durchsuchen

HEFTARCHIV | NEWS | E-BIBLIOTHEK | VIDEO | BLOGS | WHITEPAPER | EVENTS | ACADEMY | ABO | SHOP

user friendly

  Home  »  Heft & Abo  »  Heftarchiv  »  2003  »  04  »  Klon-Debatte  

RSS-Feed der aktuellen News von Linux-Magazin Online Folgen Sie Linux-Magazin Online auf Twitter
Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark

Prozesse und Threads - Hintergrund und aktuelle Entwicklungen

Klon-Debatte

von Wolfgang Hetzler, Ulrich Wolf
Erschienen im Linux-Magazin 2003/04

Die Thread-Behandlung ist mitentscheidend für die Performance und Parallelisierbarkeit von Linux-Anwendungen. Im folgenden Beitrag geht es darum, wie Threads und Prozesse arbeiten und wie die aktuellen Entwicklungen auf diesem Gebiet aussehen.

Alle modernen Betriebssysteme benutzen präemptives Multitasking, um eine Vielzahl der Aktivitäten gerecht auf die Ressource Prozessor zu verteilen. Dazu gibt es zwei Möglichkeiten: Prozesse und Threads. Prozesse sind der herkömmliche Weg, Threads die modernere Variante, Prozesse behandelt jedes Unix gleich, bei Threads gibt es eine große Vielfalt der Implementierungen.

Threads können das Entwickeln parallelisierter Anwendungen vereinfachen, viele wichtige Applikationen, die ihren Ursprung auf anderen Betriebssystemen haben, benutzen Threads sehr eifrig, Programmiersprachen wie Java bauen sogar darauf auf. Daher kam das Thema vor ein paar Jahren auch für Linux wieder verstärkt auf die Agenda.

Kein Wunder also, dass die Hardware-Industrie hier zum Teil selbst das Heft in die Hand nimmt und die Entwicklung aktiv vorantreibt. Schließlich soll der von interessierten Seiten gern hervorgebrachte Vorwurf "Linux skaliert nicht" bald für immer verstummen. Das Gerangel um die beste Lösung für Linux ist gegenwärtig in vollem Gange, wir stellen die drei aussichtsreichsten Kandidaten vor. Zunächst aber - notgedrungen - ein bisschen Theorie.

Schwergewichte und Leichtathleten

Der Prozessgedanke ist einer der elementaren Aspekte von Unix. Ältere Betriebssysteme kennen ähnliche Begriffe wie Task oder Jobs, also Arbeitseinheiten, denen Betriebsmittel über das Betriebssystem zugeordnet werden. In drei Worten bringt es beispielsweise der Betriebssystem-Professor Andrew Tanenbaum auf den Punkt: Ein Prozess ist ein "Programm in Aus-führung".

Die Implementierung von Prozessen unter Linux weist kaum Unterschiede zu klassischen Unix-Prozessen auf. Der Kernel legt durch das Scheduling fest, wie lange ein Prozess die Ressourcen des Systems in Anspruch nehmen darf. Aber die Scheduling-Algorithmen können je nach Linux- oder Unix-Version unterschiedlich sein. Die einzige Möglichkeit, einen neuen Prozess zu erzeugen, ist der Systemcall »fork()« (oder dessen ältere Variante »vfork()«), den ein schon bestehender Vaterprozess ausführen muss.

Der neue Prozess ist zunächst eine perfekte Kopie des alten, einschließlich Speicherabbild, aller Variablen und Register. Der Kindprozess besitzt also jetzt eine vollständige Kopie des Adressraums des Vaterprozesses für sich, gemeinsam genutzten Speicher gibt es nicht, von Besonderheiten wie Shared Memory natürlich abgesehen. Zur Unterscheidung von Vater- und Kindprozess dient die Prozess-ID. Der Systemcall fork»()« liefert einen positiven Integerwert an den Vaterprozess zurück, der Rückgabewert an den Kindprozess ist »0«.

In der Praxis ist das vollständige Kopieren das Speicherinhalts beim Fork zu aufwändig, da eine ganze Reihe aufeinander folgender Speicherzugriffe nötig ist. Deshalb kommt bei allen modernen Unix-Versionen und auch bei Linux eine Technik namens Copy-on-Write zum Zuge. Der Kindprozess erhält zwar eigene Page Tables, sie zeigen allerdings noch auf die Pages des Vaters und sind für den Kindprozess schreibgeschützt. Erst wenn einer der Prozesse versucht auf eine Page zu schreiben, wird diese tatsächlich kopiert.

Der Aufruf des Systemcalls »fork« geschieht mit der Funktion »do_fork()«, das zentrale Element zum Speichern von Informationen über Prozesse ist die Struktur »task_struct«, der so genannte Prozessdeskriptor. Die Deskriptoren aller Prozesse sind über eine doppelt verkettete Liste verbunden.

Eine besondere Art von Prozessen sind die Threads, in einer anderen Terminologie auch Light Weight Processes (LWP) genannt, die eine Erweiterung des Unix-Standards sind. Linux benutzt dazu den Systemcall »clone()« (»man 2 clone«) den es im Posix-Standard von Unix nicht gibt. Der Aufruf funktioniert ähnlich wie »fork«, nur dass es »clone()« dem Kind-"Prozess" ermöglicht, sich Ressourcen mit dem aufrufenden Prozess zu teilen. Über eine Bitmap, die »sharing_flags«, legt der Programmierer fest, welches Erbe das Kind mitbekommt. In früheren Linux-Versionen bestand diese Bitmap aus 5 Bits, in Version 2.5 ist sie auf 17 angewachsen.

Das wichtigste Bit ist »CLONE_VM«, ist es gesetzt, nutzt der neue Prozess den Adressraum des alten mit und es entsteht ein LWP, also ein Thread. Das Bit »CLONE_FS« regelt, ob Verzeichnisse und die »umask« geteilt werden. Ein gesetztes »CLONE_FILES«-Bit bewirkt, dass die File-Deskriptoren gemeinsam sind und »CLONE_SIGHAND« tut dasselbe für die Signalhandler.

Etwas tückisch ist »CLONE_PID«, hier könnte man vermuten, dass der Programmierer die Wahl hat, den Thread mit der PID des Vaters zu erzeugen. Dem ist aber nicht so. Nur Prozesse mit PID »0«, so genannte »idlestasks«, dürfen dieses Bit setzen. In Mehrprozessorsystemen gibt es eine »idlestask« pro CPU. Im Kernel 2.5 ist »CLONE_PID« in »CLONE_IDLETASK « umbenannt, um diese Verwirrung zu beseitigen.

Eine Besonderheit, die auch zur Verwirrung beiträgt, sind Threads, die gelegentlich Service-Threads, manchmal aber auch Kernel-Threads genannt werden. Das Problem ist, dass auch die bisher erwähnten Threads, da auf Kernelebene implementiert, oft Kernel-Thread heißen. Deren Sonderform, also die Service-Threads, verbringen im Gegensatz zu normalen Prozessen und Threads ihr ganzes Leben im Kernelspace und sind normalerweise dazu da, eine einzige spezifische Kernelfunktion auszuführen. Der erwähnte Prozess mit der PID »0« ist so ein Kernel-Thread. Kernel-Threads werden mit der Funktion »kernel _thread()« erzeugt, die (wie »clone()«) die Funktion »do_fork()« nutzt.

Posix-Threads als gemeinsamer Nenner

Threads haben eine ganze Reihe von Vorteile gegenüber den schwergewichtigen Prozessen. Durch die gemeinsam genutzten Ressourcen ist eine bessere Performance möglich, als wenn die gleiche Aufgabe durch mehrere Prozesse erledigt werden müsste; aufwändige Interprozess-Kommunikation, zum Beispiel mittels Pipes, entfällt. Auf Mehrprozessorsystemen können Threads für eine bessere Auslastung sorgen, indem sich Threads eines Prozesses auf verschiedene CPUs verteilen.

Nachteile gibt es natürlich auch, die Synchronisation von Threads ist sehr komplex. Und schließlich: Alles, was mittels »clone« passiert, ist Linux-spezifisch und nicht portierbar. Da dieses Problem nicht neu ist, sondern in der Unix-Geschichte schon früher auftrat, ist es Teil der großen Standardisierungsbemühung Posix, und zwar im Standard IEEE 1003.1c, er definiert die oft zitierten Posix-Threads.


Abbildung 1: Das »AUTHORS«-File von NGPT zeigt, dass den Autoren auch Nicht-Intel-Systeme wichtig waren, zumindest die von IBM.

Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark
Ähnliche Artikel
Zwillingsforschung Technik, Marktübersicht und Grundlagen zu Mehrkern-Prozessoren
Baukasten Ein Template-basiertes Programmiermodell für Multicore
Sonnenstudio Suns Entwicklungsumgebung Studio unter Linux
Senkrechtstarter KVM verzeichnet Geländegewinne
Eingestöpselt Mehr als nur Hardware-Treiber: Grundlagen der Kernelmodule
Schneller parallel? GNU Compiler Collection 4.2
Whitepaper
Daten Migration - Eine Publikation von Bloor Research

Datenmigrationsprojekte überschreiten häufig das Budget, neigen zu Verzögerung und werden unter Umständen komplett abgebrochen. Bloor Research ist eines der weltweit führenden IT-Forschungs-, Analyse- und Beratungsunternehmen und wird in dem vorliegenden White Paper die wichtigsten Aspekte dieser Problematik näher beleuchten. Ferner werden praktische Empfehlungen für erfolgreiche Migrationsprojekte gegeben, die Sie auf Ihr nächstes Projekt übertragen können.

Download PDF (Registrierung erforderlich)
Open Source Datenintegration in der Praxis: Fallstudien und Anwendungsbeispiele

Über die letzten Jahre hinweg haben sich Open Source Lösungen als fester Bestandteil des gesamten Datenintegrationsmarktes etabliert. Viele Unternehmen haben bereits das Open Source Modell für Ihre Datenintegrationsprojekte aufgegriffen. Das vorliegende White Paper illustriert anhand ausgewählter Fallstudien und Anwendungsbeispiele die Implementierung von Open Source Datenintegration in der Praxis und benennt die daraus resultierenden Vorteile.

Download PDF (Registrierung erforderlich)
Kommentare (0)