Ich habe das Buch Linux Kernel Development on Chapter Process Scheduling gelesen . Auf Seite 61, Abschnitt Aufwachen , lautet der erste Absatz:
Das Aufwecken erfolgt über wake_up (), wodurch alle in der angegebenen Warteschlange wartenden Aufgaben aktiviert werden . Es ( Q1 : worauf bezieht
it
sich das ?) Ruft try_to_wake_up () auf, wodurch der Status der Aufgabe ( Q2 : welche Aufgabe? Alle aufgeweckten Aufgaben? ) Auf TASK_RUNNING gesetzt wird, und ruft enqueue_task () auf, um die Aufgabe dem rot-schwarzen Baum hinzuzufügen. und setzt need_resched, wenn die Priorität der aufgeweckten Aufgabe höher ist als die Priorität der aktuellen Aufgabe. Der Code, der das Auftreten des Ereignisses verursacht, ruft normalerweise wake_up () selbst auf. Wenn beispielsweise Daten von der Festplatte eingehen, ruft das VFS wake_up () in der Warteschlange auf, in der sich die auf die Daten wartenden Prozesse befinden.
Ich bin ziemlich verwirrt über das Obige. Lassen Sie mich nur das Beispiel im obigen Absatz verwenden, dh die Festplatte wurde nach dem Lesen der Daten unterbrochen, aber mit einem vollständigeren Bild. Bitte korrigieren Sie mich, wenn eine der folgenden Angaben falsch oder unvollständig ist:
Einige Benutzerprozesse haben eine blockierende Leseoperation ausgegeben, die einen Systemaufruf auslöst, und der Prozess befindet sich im Bereich des Kernels.
Der Kernel richtet den Festplattencontroller ein, der die erforderlichen Daten anfordert, und versetzt diesen Prozess in den Ruhezustand (dieser Prozess wird in eine Warteschlange gestellt). Der Kernel plant die Ausführung eines anderen Prozesses.
Festplatteninterrupt tritt auf. Die CPU unterbricht den aktuell ausgeführten Prozess und springt zur Behandlung von Festplatteninterrupts.
Der Festplattencontroller wird irgendwann während der Interrupt-Behandlung aktiviert, um die von der Festplatte gelesenen Daten in den Hauptspeicher zu übertragen (entweder unter der Leitung der CPU oder per DMA).
(Nicht sicher, bitte korrigieren) Wie im Absatz angegeben, ruft VFS wake_up () in der Warteschlange auf, in der die Prozesse auf die Daten warten.
Meine spezifischen Fragen sind folgende:
Q1 (siehe zitierten Absatz): Ich gehe davon aus, dass sich das It im zweiten Satz auf die Funktion bezieht wake_up()
. Warum wake_up
weckt die Funktion alle Aufgaben, anstatt nur die, die auf diese Datenträgerdaten wartet?
F2 (siehe zitierten Absatz): Kennt try_to_wake_up()
irgendwie die spezifische Aufgabe, deren Status auf TASK_RUNNING gesetzt werden muss? Oder try_to_wake_up()
setzt der Status aller aufgeweckten Aufgaben auf TASK_RUNNING?
F3 : Wie viele Warteschlangen muss der Kernel verwalten? Wenn es mehr als zwei solcher Warteschlangen gibt, woher weiß der Kernel, welche Warteschlange er auswählen soll, sodass sich der Prozess, der auf die Datenträgerdaten wartet, in dieser Warteschlange befindet?
F4 : Angenommen, wir kennen die Warteschlange, in der der Wartevorgang läuft. Woher weiß der Kernel, welcher Prozess auf die Daten von der Festplatte wartet? Ich kann mir nur vorstellen, dass einige Informationen, die für den Prozess spezifisch sind, der die Datenträgerdaten anfordert, an den Datenträgercontroller übergeben werden, z. B. die PID, die Speicheradresse des Prozesses oder etwas anderes. Nach Abschluss der Interrupt-Behandlung verwendet der Festplattencontroller (oder Kernel?) Diese Informationen, um den Prozess in der Warteschlange zu lokalisieren.
Bitte helfen Sie mir, dieses Bild des Prozesses wake_up zu vervollständigen! Vielen Dank!
quelle
wake_up
alle Prozesse aufgeweckt werden, aber am Ende ist es möglich, dass nur eine Teilmenge von Prozessen wirklich ausgeführt werden kann.Um auf Gilles 'Antwort aufzubauen,
F2 : Ich bin mir nicht sicher, aber ich würde die Passage aus dem Buch so interpretieren, dass der Interrupt-Handler
wake_up()
einmal aufruft (die Warteschlangen-ID als Argument übergibt) und für jeden Prozesswake_up()
aufrufttry_to_wake_up()
, der sich in dieser Warteschlange befindet. (Dies wiederholt Gilles 'Antwort auf Q1 : Es werden nicht alle Aufgaben aktiviert, sondern nur diejenigen, die sich in der Warteschlange befinden, die dem aufgerufenen Ereignis zugeordnet istwake_up()
.)F3 : Jede Warteschlange gehört einem Teil des Kernel-Codes - meistens Gerätetreiber, andere. Die Routine, die eine Warteschlange besitzt, weist ihr eine eindeutige Kennung zu, die auf einem eindeutigen Merkmal des Ereignisses basiert, für das die Warteschlange bestimmt ist. Wenn es (der Treiber / das andere Modul) einen Prozess in den Ruhezustand versetzt, gibt es (anhand der ID) an, in welche Warteschlange er gestellt werden soll. Die aufrufende Routine
wake_up()
(normalerweise ein Interrupt-Handler) muss Teil desselben Moduls sein, das den Prozess in den Ruhezustand versetzt, damit sie die Kennung für die Warteschlange kennt, die dem aufgetretenen Ereignis entspricht.Als ich mir das letzte Mal den Unix-Kernel-Quellcode angesehen habe (vor vielen Jahren), hatten die Festplattentreiber für jede E / A-Anforderung eine andere Ereignis-ID. Wie Gilles sagt, können mehrere Prozesse auf dasselbe Ereignis warten, wenn sie dieselbe Datei gleichzeitig lesen. (Dies bezieht sich natürlich auch auf Q1 .)
F4 : Wenn ich den Satz "Festplattencontroller" höre, denke ich an Hardware. Aber abgesehen davon hast du recht; die Plattentreiber (ein Software - Modul in dem Kernel) hat (zumindest potenziell) den Zugang zu allen Informationen zu jedem Prozess, ruft sie (dh durch Scheibe tut I / O). Wenn der Festplattentreiber einen Prozess in den Ruhezustand versetzt, weil er eine physische E / A initiiert hat, deren Abschluss einige Zeit in Anspruch nimmt, stellt er (der Treiber) die PID, die Speicheradresse oder etwas anderes des Prozesses in die Warteschlange. Was auch immer dies ist, es reicht aus,
try_to_wake_up()
um den Prozess zu wecken.Der letzte Satz der von Ihnen zitierten Passage lautet: „… VFS ruft wake_up () in der Warteschlange auf…“. Ich frage mich, ob dies buchstäblich richtig ist. Dateisystemcode ist eine Schicht über dem Festplattentreiber. Ich würde erwarten, dass der Interrupt (ein Signal von der Festplattenhardware an die CPU) vom Festplatten-Interrupt-Handler (Teil des Festplattentreibers) verarbeitet wird, der die wartenden Prozesse (durch Aufrufen
wake_up()
) aufweckt . Der Treiber weckte anschließend den Dateisystemcode. (Diese Terminologie ist möglicherweise auch ungenau. Es ist möglicherweise besser zu sagen, dass der Treiber etwas unternimmt, damit der Dateisystemcode die Verarbeitung wieder aufnehmen kann.) Der Dateisystemcode kehrt dann möglicherweise zum Benutzerprozess zurück oder ruft den Festplattentreiber erneut auf. was dazu führt, dass der Prozess wieder eingeschläfert wird.Ich streite mit deinem Schritt # 4. Wenn ein Gerät DMA verwendet, wird es erst nach Abschluss der Datenübertragung unterbrochen.
quelle
Das Problem, das Sie beim Aufwecken aller wartenden Prozesse anführen, ist das sogenannte "donnernde Herdenproblem" (viele Prozesse werden aufgeweckt, wenn eine Ressource verfügbar wird, sie streiten sich darum, welcher einen exklusiven Zugriff auf die Ressource erhält, die anderen schlafen wieder ein ). Dies wird zu einem Problem, wenn es viele Prozessoren gibt und daher hier viele Prozessoren kämpfen. Neuere Linux-Versionen lösen dieses Problem, indem sie nur einen der wartenden Prozesse aktivieren.
Meistens wartet ein (oder nur wenige) Prozess auf ein bestimmtes Ereignis (es gibt keine feste, viel weniger kleine Anzahl von Ereignissen, auf die ein Prozess warten kann).
Gilles 'Antwort geht Ihre Punkte einzeln durch, nicht viel, um das hier hinzuzufügen.
quelle