Betriebssystemtheorie/ Threads
Definition
BearbeitenThreads (<engl.> Faden) sind die Ausführungseinheiten eines Prozesses. Sie werden vom Thread-Scheduler auf einen Prozessor zugeteilt und dort ausgeführt. Man unterscheidet zwischen zwei Formen:
- Kernel-Threads
- Jeder Thread eines Prozesses wird vom Kern verwaltet. Der CPU-Scheduler verteilt die Rechenzeit der Prozessoren direkt an Threads. Diese Methode ist in vielen heute verbreiteten Betriebssystemen implementiert.
- User-Level-Threads
- Der Kern verwaltet nur Prozesse. Bei einem Prozess mit mehr als einem Thread ist die gesamte Verwaltung im Programm selbst implementiert. Der CPU-Scheduler verteilt die Prozessoren an Prozesse, nicht an Threads. Da die gesamte Thread-Implementierung im Userspace ist, enthält der Prozess die nötigen Mechanismen, einen seiner Threads auszuwählen. Diese Vorgehensweise hat einige Nachteile und heute kaum üblich.
Manchmal werden Threads als leichtgewichtige Prozesse bezeichnet. Dieser Ausdruck ist allerdings irreführend. Er impliziert, dass Threads und Prozesse austauschbar sind und sollte deshalb vermieden werden.
Kernel threads
BearbeitenWie bereits beschrieben sind Kernel-Threads komplett im Betriebssystem implementiert. Ein Thread wird dabei im Kern durch einen Thread Control Block (TCB) repräsentiert. Der TCB enthält den Zustand des Threads am Ende seiner letzten Zeitscheibe, beziehungsweise einen Initialzustand, falls ein Thread noch nie gerechnet wurde. Folgende Werte finden sich im TCB:
- Instructionpointer IP
- Der Instructionpointer ist ein CPU-Register welches die Adresse des nächsten Befehls enthält, den der Thread ausführen wird.
- Stackpointer SP
- Für seine Ausführung benötigt jeder Thread ein Stück Arbeitsspeicher, auf dem lokale Variablen und Rücksprungadressen gespeichert werden. Dieser Speicher ist wie ein Stapel organisiert, bei dem die aktuellsten Werte ganz oben liegen und die ältesten ganz unten. Daher auch der Name Stapel. Der Stackpointer zeigt auf den obersten Wert des Stapels; welcher interessanterweise im Speicher vor den älteren Werten steht.
- Kernelstack pointer
- Während der Thread sich im Kernmodus befindet wird ein separater Stack verwendet. Ansonsten gilt das Gleiche wie für den normalen Stackpointer.
- General Purpose Register
- Alle beliebig verwendbaren Register werden unter dem Begriff General Purpose Register zusammengefasst. Beim x86 zählen dazu unter anderem %eax, %ebx usw.
- FPU-Register
- Die Register des numerischen Koprozessors werden zusammen mit den anderen Registern im TCB gespeichert.
- Weitere Informationen
- Dazu gehören Parameter für Scheduler, Priorität, spezielle Anforderungen des Threads an das System und ähnliches. Diese Teile des TCB werden nicht in die CPU geladen.
Die Zustände, in dem sich Threads befinden können, sind weitestgehend mit den Zuständen für Prozesse identisch. Die einzige Ausnahme bildet dead, da ein Thread strenggenommen nicht "tot" sein kann. Hat ein Thread seine Aufgabe erfüllt, wird er aus dem System entfernt. In manchen Systemen, wie L4, ist dazu keine Möglichkeit vorgesehen. Dort werden überflüssige Threads einfach auf blocked geschaltet und warten auf eine Ressource, die nie freigegeben wird.
Abhängig seinem Zustand wird jeder TCB wird vom Kern in eine Liste eingehängt. Die Threads in der sogenannten ready-queue sind bereit einen Zeitscheibe zugeteilt zu bekommen und werden vom CPU-Scheduler bedient. Die wartenden Threads befinden sich in der waiting-queue. Sobald das Ereignis eintritt, auf dass ein Thread wartet, wird er in die ready-queue umgehängt.