Wie findet der Linux-Kernel heraus, welcher Prozess während der Interrupt-Behandlung aktiviert werden soll?


7

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 itsich 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:

  1. Einige Benutzerprozesse haben eine blockierende Leseoperation ausgegeben, die einen Systemaufruf auslöst, und der Prozess befindet sich im Bereich des Kernels.

  2. 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.

  3. Festplatteninterrupt tritt auf. Die CPU unterbricht den aktuell ausgeführten Prozess und springt zur Behandlung von Festplatteninterrupts.

  4. 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).

  5. (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_upweckt 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!

Antworten:


7

Q1: "Es" ist wake_up. Es werden alle Aufgaben aktiviert , die auf die Festplattendaten warten . Wenn sie nicht auf diese Daten warten würden, würden sie nicht auf diese Warteschlange warten.

F2: Ich bin nicht sicher, ob ich die Frage verstehe. Jeder Wake-Queue-Eintrag enthält einen Zeiger auf die Aufgabe. try_to_wake_uperhält einen Zeiger auf die Aufgabe, die aufgeweckt werden soll. Es wird einmal pro Funktion aufgerufen.

F3: Es gibt viele Warteschlangen. Es gibt eine für jedes Ereignis, das passieren kann. Der Festplattentreiber richtet eine Warteschlange für jede Anforderung an die Festplatte ein. Wenn der Dateisystemtreiber beispielsweise den Inhalt eines bestimmten Festplattenblocks wünscht, fragt er den Festplattentreiber nach diesem Block, und die Anforderung beginnt mit der Aufgabe, die die Dateisystemanforderung gestellt hat. Andere Einträge können zur Wartewarteschlange hinzugefügt werden, wenn eine andere Anforderung für denselben Block eingeht, während dieser noch aussteht.

Wenn ein Interrupt auftritt, ermittelt der Festplattentreiber anhand der von der Hardware übergebenen Informationen, auf welcher Festplatte Daten verfügbar sind, und sucht in der Datenstruktur, die die Kerneldaten für diese Festplatte enthält, um festzustellen, welche Anforderung erfüllt werden sollte. In dieser Datenstruktur befinden sich unter anderem der Ort, an dem die Daten geschrieben werden sollen, und die entsprechende Weckwarteschlange, die angibt, was als nächstes zu tun ist.

F4: Der Prozess führt einen Systemaufruf durch, beispielsweise um eine Datei zu lesen. Dies löst einen Code im Dateisystemtreiber aus, der bestimmt, dass die Daten von der Festplatte geladen werden müssen. Dieser Code sendet eine Anforderung an den Festplattentreiber und fügt den aufrufenden Prozess der Warteschlange der Anforderung hinzu. (Es gibt tatsächlich mehr Ebenen als diese, aber Sie haben die Idee.) Wenn der Lesevorgang abgeschlossen ist, wird das Warteschlangenereignis ausgelöst und der Prozess wird somit aus der Warteschlange der Festplatte entfernt. Der durch das Warteschlangenereignis ausgelöste Code ist eine vom Dateisystemtreiber bereitgestellte Funktion, die die Daten in den Speicher des Prozesses kopiert und den readSystemaufruf zurückgibt.


Ich gehe davon aus, dass sich in der Warteschlange der Festplatte mehrere Prozesse befinden können. Welcher Prozess wird nach Abschluss des Lesevorgangs aus der Warteschlange der Festplatte entfernt? Die Vorderseite der Warteschlange?
Rich

@ Rich Alle von ihnen. Nun, alle, die ihre Lektüre abgeschlossen haben. Ich weiß nicht genau, wie Festplattentreiber organisiert sind: ob es eine einzelne Warteschlange für die Festplatte gibt (mit allen Prozessen, die auf die Festplatte warten) oder eine pro Anforderung (jeweils mit den Prozessen, die auf diesen bestimmten Sektor warten).
Gilles 'SO - hör auf böse zu sein'

OH? Was aber, wenn die von der Festplatte gelesenen Daten nur für einen der Prozesse in der Warteschlange spezifisch waren?
Rich

Es ist also Aufgabe des Festplattentreibers, herauszufinden, welche Prozessanforderungen erfüllt sind. Könnte es vorkommen, dass nur einige der in der Warteschlange wartenden Prozesse aufgeweckt werden können, weil die Anforderungen anderer Prozesse nicht vollständig erfüllt wurden? Ich denke, meine allgemeine Verwirrung ist, dass wake_upalle Prozesse aufgeweckt werden, aber am Ende ist es möglich, dass nur eine Teilmenge von Prozessen wirklich ausgeführt werden kann.
Rich

@Rich Es gibt viele Bedingungen, die dazu führen können, dass ein Prozess nicht ausgeführt werden kann, z. B. wenn er angehalten wird. Ich kenne den Linux-Kernel nicht gut genug, um zu wissen, ob sie in diesem Fall aus der Warteschlange der Festplatte entfernt werden. Ich denke, dass dies im Allgemeinen der Fall ist, da sich sonst die Warteschlange und alle ähnlichen Warteschlangen mit Prozessen füllen würden, die nicht aufgeweckt werden können und die Leistung beeinträchtigen würden. Im Allgemeinen möchten Sie als OS-Designer nicht, dass Prozesse unnötig aufgeweckt werden. Wir versuchen, dies nur unter Rennbedingungen zu erreichen (wenn der Grund für das Aufwachen gerade verschwunden ist).
Gilles 'SO - hör auf böse zu sein'

2

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 Prozess wake_up() aufruft try_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 ist wake_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.


1

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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.