Manchmal, wenn ich ein Programm unter Linux schreibe und es aufgrund eines Fehlers abstürzt, wird es zu einem unterbrechungsfreien Prozess und läuft für immer weiter, bis ich meinen Computer neu starte (selbst wenn ich mich abmelde). Meine Fragen sind:
- Was führt dazu, dass ein Prozess nicht mehr unterbrochen werden kann?
- Wie kann ich das verhindern?
- Dies ist wahrscheinlich eine dumme Frage, aber gibt es eine Möglichkeit, sie zu unterbrechen, ohne meinen Computer neu zu starten?
linux
scheduling
preemption
Jason Baker
quelle
quelle
TASK_UNINTERUPTIBLE
Zustand versetzt wird, wenn sich das System nicht im Ruhezustand befindet, wodurch zwangsweise Daten gesammelt werden, die auf die Übertragung warten, sobald der Superuser beendet wird? Dies wäre eine Goldmine für Hacker, um Informationen abzurufen, in den Zombie-Status zurückzukehren und Informationen im Leerlauf über das Netzwerk zu übertragen. Einige können argumentieren, dass dies eine Möglichkeit ist, eineBlackdoor
für die Mächte zu schaffen, jedes System wie gewünscht zu betreten und zu verlassen. Ich bin der festenAntworten:
Ein unterbrechungsfreier Prozess ist ein Prozess, der sich zufällig in einem Systemaufruf (Kernelfunktion) befindet und nicht durch ein Signal unterbrochen werden kann.
Um zu verstehen, was das bedeutet, müssen Sie das Konzept eines unterbrechbaren Systemaufrufs verstehen. Das klassische Beispiel ist
read()
. Dies ist ein Systemaufruf, der lange (Sekunden) dauern kann, da möglicherweise eine Festplatte hochgefahren oder Köpfe bewegt werden müssen. Während der meisten Zeit wird der Prozess in den Ruhezustand versetzt und blockiert die Hardware.Während der Prozess im Systemaufruf schläft, kann er ein asynchrones Unix-Signal empfangen (z. B. SIGTERM). Dann geschieht Folgendes:
Wenn Sie frühzeitig vom Systemaufruf zurückkehren, kann der Benutzerbereichscode sein Verhalten als Reaktion auf das Signal sofort ändern. Zum Beispiel sauber als Reaktion auf SIGINT oder SIGTERM beenden.
Andererseits dürfen einige Systemaufrufe auf diese Weise nicht unterbrochen werden. Wenn das System aus irgendeinem Grund Blockierungen aufruft, kann der Prozess auf unbestimmte Zeit in diesem nicht tötbaren Zustand bleiben.
LWN hat im Juli einen schönen Artikel veröffentlicht , der dieses Thema berührt.
So beantworten Sie die ursprüngliche Frage:
So verhindern Sie dies: Finden Sie heraus, welcher Treiber Ihnen Probleme bereitet, und stellen Sie die Verwendung entweder ein oder werden Sie ein Kernel-Hacker, und beheben Sie das Problem.
So beenden Sie einen unterbrechungsfreien Prozess ohne Neustart: Lassen Sie den Systemaufruf irgendwie beenden. Häufig ist es am effektivsten, das Netzkabel zu ziehen, ohne den Netzschalter zu betätigen. Sie können auch ein Kernel-Hacker werden und den Treiber dazu bringen, TASK_KILLABLE zu verwenden, wie im LWN-Artikel erläutert.
quelle
Wenn sich ein Prozess im Benutzermodus befindet, kann er jederzeit unterbrochen werden (Umschalten in den Kernelmodus). Wenn der Kernel in den Benutzermodus zurückkehrt, prüft er, ob Signale anstehen (einschließlich derjenigen, die zum Beenden des Prozesses verwendet werden, wie z. B.
SIGTERM
undSIGKILL
). Dies bedeutet, dass ein Prozess nur bei Rückkehr in den Benutzermodus abgebrochen werden kann.Der Grund, warum ein Prozess im Kernelmodus nicht beendet werden kann, besteht darin, dass er möglicherweise die Kernelstrukturen beschädigen kann, die von allen anderen Prozessen auf demselben Computer verwendet werden (auf die gleiche Weise kann das Beenden eines Threads möglicherweise Datenstrukturen beschädigen, die von anderen Threads im selben Prozess verwendet werden). .
Wenn der Kernel etwas tun muss, das lange dauern kann (z. B. Warten auf eine Pipe, die von einem anderen Prozess geschrieben wurde, oder Warten, bis die Hardware etwas tut), schläft er, indem er sich als "Sleeping" markiert und den Scheduler aufruft, um zu einem anderen zu wechseln Prozess (wenn es keinen nicht schlafenden Prozess gibt, wechselt er zu einem "Dummy" -Prozess, der die CPU anweist, etwas langsamer zu werden, und sich in einer Schleife befindet - der Leerlaufschleife).
Wenn ein Signal an einen Ruhevorgang gesendet wird, muss es aufgeweckt werden, bevor es in den Benutzerbereich zurückkehrt und somit das anstehende Signal verarbeitet. Hier haben wir den Unterschied zwischen den beiden Hauptschlafarten:
TASK_INTERRUPTIBLE
, der unterbrechbare Schlaf. Wenn eine Aufgabe mit diesem Flag markiert ist, schläft sie, kann aber durch Signale geweckt werden. Dies bedeutet, dass der Code, der die Aufgabe als schlafend markiert hat, ein mögliches Signal erwartet und nach dem Aufwachen danach sucht und vom Systemaufruf zurückkehrt. Nachdem das Signal verarbeitet wurde, kann der Systemaufruf möglicherweise automatisch neu gestartet werden (und ich werde nicht näher darauf eingehen, wie das funktioniert).TASK_UNINTERRUPTIBLE
, der ununterbrochene Schlaf. Wenn eine Aufgabe mit diesem Flag markiert ist, erwartet sie nicht, von etwas anderem als dem, worauf sie wartet, geweckt zu werden, entweder weil sie nicht einfach neu gestartet werden kann oder weil Programme erwarten, dass der Systemaufruf atomar ist. Dies kann auch für Schlafstörungen verwendet werden, von denen bekannt ist, dass sie sehr kurz sind.TASK_KILLABLE
(erwähnt in dem LWN-Artikel, auf den durch die Antwort von ddaa verwiesen wird) ist eine neue Variante.Dies beantwortet Ihre erste Frage. Zu Ihrer zweiten Frage: Sie können einen unterbrechungsfreien Schlaf nicht vermeiden, er ist eine normale Sache (dies geschieht beispielsweise jedes Mal, wenn ein Prozess von / auf die Festplatte liest / schreibt). Sie sollten jedoch nur einen Bruchteil einer Sekunde dauern. Wenn sie viel länger dauern, handelt es sich normalerweise um ein Hardwareproblem (oder ein Gerätetreiberproblem, das für den Kernel gleich aussieht), bei dem der Gerätetreiber darauf wartet, dass die Hardware etwas tut, was niemals passieren wird. Dies kann auch bedeuten, dass Sie NFS verwenden und der NFS-Server nicht verfügbar ist (er wartet auf die Wiederherstellung des Servers; Sie können auch die Option "intr" verwenden, um das Problem zu vermeiden).
Der Grund, warum Sie nicht wiederherstellen können, ist derselbe, warum der Kernel wartet, bis er in den Benutzermodus zurückkehrt, um ein Signal zu liefern oder den Prozess abzubrechen: Dies würde möglicherweise die Datenstrukturen des Kernels beschädigen (Code, der auf einen unterbrechbaren Ruhezustand wartet, kann einen Fehler erhalten, der ihn anzeigt um in den Benutzerbereich zurückzukehren, in dem der Prozess abgebrochen werden kann; Code, der auf einen unterbrechungsfreien Ruhezustand wartet, erwartet keinen Fehler).
quelle
Unterbrechungsfreie Prozesse warten normalerweise auf E / A nach einem Seitenfehler.
Bedenken Sie:
Der Prozess / die Aufgabe kann in diesem Zustand nicht unterbrochen werden, da keine Signale verarbeitet werden können. Wenn dies der Fall wäre, würde ein weiterer Seitenfehler auftreten und es würde wieder dort sein, wo es war.
Wenn ich "Prozess" sage, meine ich wirklich "Aufgabe", was unter Linux (2.6) grob in "Thread" übersetzt wird, der möglicherweise einen einzelnen "Threadgruppen" -Eintrag in / proc hat oder nicht
In einigen Fällen kann es lange dauern. Ein typisches Beispiel hierfür ist, wenn sich die ausführbare Datei oder die mmap-Datei in einem Netzwerkdateisystem befindet, in dem der Server ausgefallen ist. Wenn die E / A schließlich erfolgreich ist, wird die Aufgabe fortgesetzt. Wenn es irgendwann fehlschlägt, bekommt die Aufgabe im Allgemeinen einen SIGBUS oder so.
quelle
Zu Ihrer dritten Frage: Ich denke, Sie können die unterbrechungsfreien Prozesse durch Ausführen beenden
sudo kill -HUP 1
. Es wird init neu starten, ohne die laufenden Prozesse zu beenden, und nachdem es ausgeführt wurde, waren meine unterbrechungsfreien Prozesse verschwunden.quelle
Wenn Sie von einem "Zombie" -Prozess sprechen (der in der ps-Ausgabe als "Zombie" bezeichnet wird), ist dies ein harmloser Datensatz in der Prozessliste, der darauf wartet, dass jemand seinen Rückkehrcode sammelt, und er kann ignoriert werden.
Könnten Sie bitte beschreiben, was und "unterbrechungsfreier Prozess" für Sie ist? Überlebt es den "Kill -9" und tuckert glücklich mit? Wenn dies der Fall ist, bleibt es bei einem Systemaufruf hängen, der in einem Treiber steckt, und Sie bleiben bei diesem Prozess bis zum Neustart (und manchmal ist es besser, bald neu zu starten) oder dem Entladen des entsprechenden Treibers (was unwahrscheinlich ist) stecken. . Sie könnten versuchen, mit "strace" herauszufinden, wo Ihr Prozess steckt, und ihn in Zukunft vermeiden.
quelle