Kontextwechsel Interna
Mit Hilfe dieser Frage möchte ich Wissenslücken schließen und lernen.
Ein Benutzer führt also einen Thread (auf Kernel-Ebene) aus und ruft ihn jetzt aufyield
(ein Systemaufruf nehme ich an). Der Scheduler muss nun den Kontext des aktuellen Threads im TCB (der irgendwo im Kernel gespeichert ist) speichern und einen anderen Thread zum Ausführen auswählen, seinen Kontext laden und zu seinem springenCS:EIP
. Um die Sache einzugrenzen, arbeite ich an Linux, das auf x86-Architektur läuft. Nun möchte ich auf die Details eingehen:
Also, zuerst haben wir einen Systemaufruf:
1) Die Wrapper-Funktion füryield
schiebt die Systemaufrufargumente auf den Stapel. Drücken Sie die Rücksendeadresse und lösen Sie einen Interrupt aus, wenn die Systemrufnummer auf eine Registrierkasse gedrückt wird (sagen wirEAX
).
2) Der Interrupt wechselt den CPU-Modus von Benutzer zu Kernel und springt zur Interrupt-Vektortabelle und von dort zum eigentlichen Systemaufruf im Kernel.
3) Ich denke, der Scheduler wird jetzt aufgerufen und muss jetzt den aktuellen Status im TCB speichern. Hier ist mein Dilemma. Da der Scheduler den Kernel - Stack und nicht den User - Stack für die Ausführung seiner Operation verwendet (was bedeutet, dass derSS
undSP
muss geändert werden) Wie speichert es den Status des Benutzers, ohne dabei irgendwelche Register zu ändern? Ich habe in Foren gelesen, dass es spezielle Hardwareanweisungen zum Speichern des Status gibt, aber wie erhält der Scheduler dann Zugriff darauf und wer führt diese Anweisungen aus und wann?
4) Der Scheduler speichert nun den Zustand im TCB und lädt einen anderen TCB.
5) Wenn der Scheduler den ursprünglichen Thread ausführt, kehrt das Steuerelement zur Wrapper-Funktion zurück, die den Stapel löscht und den Thread fortsetzt.
Nebenfragen: Wird der Scheduler nur als Kernel-Thread ausgeführt (d. H. Als Thread, der nur Kernel-Code ausführen kann)? Gibt es für jeden Kernel-Thread oder für jeden Prozess einen eigenen Kernel-Stack?