Es ist wichtig zu verstehen, dass der Timer-Interrupt nur einer von mehreren hundert verschiedenen Gründen ist, warum schedule
aufgerufen werden könnte. Nur Programme, deren Laufzeit von Berechnungen dominiert wird, die seltener sind als man denkt, erschöpfen ihre Zeitscheibe. Es ist viel häufiger, dass Programme nur für einige Mikrosekunden - ja, Mikrosekunden - gleichzeitig ausgeführt werden, zwischen "Blockieren" in Systemaufrufen, Warten auf Benutzereingaben oder was auch immer.
Wenn ein Prozess in irgendeiner Weise beendet wird, findet letztendlich immer ein Aufruf an do_exit
im (Kernel-) Kontext dieses Prozesses statt. do_exit
ruft schedule
als seine letzte Aktion auf, und schedule
kehrt nie zu diesem Kontext zurück. Beachten Sie, dass am Ende von do_exit
ein Anruf an schedule
, unmittelbar gefolgt von BUG();
und einer Endlosschleife erfolgt.
Unmittelbar vor diesem, do_exit
ruft exit_notify
, die für das Senden SIGCHLD
an dem übergeordneten Prozess und/oder Loslassen von einem Aufruf wait
verantwortlich ist. So wird der Elternprozess oft bereit sein, wenn schedule
aufgerufen wird, und wird ausgewählt.
do_exit
freigibt auch alle dem User-Space-Zustand und ein großer Teil der Kernel-Zustand mit dem Prozess verbunden sind, gibt Speicher frei, schließt Filedeskriptoren usw. Der task_struct
selbst muss überleben, bis jemand wait
ruft, und ich kann nicht verstehen Genau wie der Kernel entscheidet, dass er jetzt freigegeben werden kann; Dieser Code ist zu kompliziert.
Wenn der Prozess genannt _exit
, die Kette Kernel Anruf einfach ist sys_exit_group
zu do_group_exit
zu do_exit
. Wenn ein fatales synchrones Signal (z. B. SIGSEGV
) erforderlich war, ist die Anrufkette viel länger und weist eine schwierige Abzweigung auf. Die Hardware-Trap wird durch einen architekturspezifischen Code (z. B. x86 do_trap
) über force_sig_info
und send_signal
bis complete_signal
angelegt, der den Task-Status einstellt und dann dem Scheduler mitteilt, den fehlerhaften Prozess aufzuwecken. Der beleidigende Prozess wacht auf und ein Labyrinth von architekturspezifischer Signalverarbeitungslogik liefert ihn schließlich an get_signal
, der do_group_exit
aufruft, der do_exit
ruft. Fatal asynchrone Signale (beispielsweise von kill 12345
an einer Shell-Eingabeaufforderung) an sys_kill
beginnen und gehen durch kill_something_info
, group_send_sig_info
, do_send_sig_info
zu send_signal
, wonach alles wie oben verläuft. In beiden Fällen können alle Schritte bis zu complete_signal
in beliebigen Prozesskontext passieren, aber alles nach dem "der beleidigende Prozess aufwacht" geschieht in diesem Kontext des Prozesses.
Die einzigen Teile dieser Beschreibung, die Linux-spezifisch sind, sind die Namen der Funktionen im Kernel-Code.Jede Implementierung von Unix wird Kernel-Funktionen haben, die mehr oder weniger was Linux do_exit
und schedule
tun, und die Abfolgen von Operationen beteiligt _exit
, fatale synchrone Signale und fatale Async-Signale werden erkennbar ähnlich sein.
Wenn Sie gemeint haben, was passiert, wenn ein Prozess 'exits()' aufruft, dann wird in diesem Fall auch der Zeitplan aufgerufen. –
viele Male Prozess kann ohne Aufruf von 'exit()' beenden. – Nullpointer
In den meisten Fällen - sie kehren zum Elternteil zurück und es ist wahrscheinlich, dass sie 'exit_group()' machen, um Dinge zu beenden; was auch endete, rief 'schedule()' auf. –