Warum können wir den unterbrechungsfreien D-Status-Prozess nicht beenden?

8

Ich habe häufig Probleme mit Prozessen, die im D-Zustand stecken bleiben, aufgrund von NFS-Freigaben hinter Firewalls. Wenn ich Verbindungen verliere, bleiben Prozesse im D-Zustand hängen und ich kann sie nicht beenden. Die einzige Lösung ist ein harter Neustart. Ich habe mich gefragt, ob es noch andere Möglichkeiten gibt, aber alle Lösungen und Informationen, die ich finden kann, sind "Sie können es einfach nicht töten". Jeder scheint damit einverstanden zu sein und zu akzeptieren, wie es ist. Ich bin etwas kritisch. Ich dachte, dass es eine Möglichkeit geben muss, den Prozess aus dem Speicher zu entfernen, damit kein Neustart erforderlich ist. Es ist sehr ärgerlich, wenn dies häufig vorkommt. Und wenn die Ressource zufällig die E / A zurückgibt, kann sie in diesem Fall einfach ignoriert werden. Warum ist das nicht möglich? Der Linux-Kernel ist meiner Meinung nach sehr fortgeschritten und Sie sollten in der Lage sein, solche Dinge zu tun. Besonders in Servern ...

Ich konnte keine zufriedenstellende Antwort finden. Warum kann / kann dies nicht implementiert werden?

Ich würde mich auch für Antworten in Bezug auf Programmierung und algorithmischen Charakter interessieren, die dieses Problem erklären würden.

Genom
quelle
1
Ich denke, es ist erwähnenswert, dass Sie im speziellen Fall von NFS-Freigaben diese mithilfe der Optionen "intr" und "soft" beim Mounten töten können. Das standardmäßige "harte" Mounten stammt aus einer Zeit, als NFS-Freigaben für das Root-Dateisystem verwendet wurden, und dort zu hängen, bis die Freigabe zurückkam, war das gewünschte Verhalten.
Kleptog

Antworten:

7

Das Beenden eines Prozesses während eines Systemaufrufs ist möglich und funktioniert meistens. Was schwierig ist, ist, es die ganze Zeit zum Laufen zu bringen. Von 99,99% auf 100% zu gehen, ist der schwierige Teil.

Wenn ein Prozess beendet wird, werden normalerweise alle von ihm verwendeten Ressourcen freigegeben. Wenn während des Prozesses E / A ausgeführt werden, wird der Code, der diese E / A ausführt, benachrichtigt und beendet, sodass die verwendeten Ressourcen freigegeben werden können.

Ein unterbrechungsfreier Schlaf tritt sichtbar auf, wenn „der Code benachrichtigt wird und beendet wird“ eine nicht zu vernachlässigende Zeit in Anspruch nimmt. Dies bedeutet, dass der Code nicht ordnungsgemäß funktioniert. Es ist ein Fehler. Ja, es ist theoretisch möglich, Code ohne Fehler zu schreiben, aber es ist praktisch unmöglich.

Sie sagen: "Wenn die Ressource das E / A zurückgibt, kann es einfach ignoriert werden." Also gut. Angenommen, ein Peripheriegerät wurde so programmiert , dass es in den zum Prozess gehörenden Speicher schreibt . Um den Prozess abzubrechen, ohne die Anforderung an das Peripheriegerät abzubrechen, muss der Speicher irgendwie in Gebrauch gehalten werden. Sie können diese Ressource nicht einfach loswerden. Es gibt Ressourcen, die bleiben müssen. Das Freigeben der anderen Ressourcen ist nur möglich, wenn der Kernel weiß, welche Ressourcen sicher freigegeben werden können. Daher muss der Code so geschrieben sein, dass er immer erkennbar ist. Die Fälle, in denen ein ununterbrochener Schlaf sichtbar lange anhält, sind Fälle, in denen es unmöglich ist, dies zu sagen, und die einzig sichere Sache ist der Weg.

Es ist möglich, ein Betriebssystem zu entwerfen, bei dem das Beenden eines Prozesses garantiert funktioniert (unter bestimmten Voraussetzungen, dass die Hardware ordnungsgemäß funktioniert). Zum Beispiel garantieren harte Echtzeitbetriebssysteme, dass das Beenden eines Prozesses höchstens eine bestimmte festgelegte Zeit in Anspruch nimmt (vorausgesetzt, es bietet überhaupt eine Kill-Funktion). Dies ist jedoch schwierig, insbesondere wenn das Betriebssystem auch eine Vielzahl von Peripheriegeräten unterstützen und eine gute Leistung im allgemeinen Fall bieten muss. Linux bevorzugt in vielerlei Hinsicht das Common-Case-Verhalten gegenüber dem Worst-Case-Verhalten.

Es ist äußerst schwierig, alle Codepfade abzudecken, insbesondere wenn es ab Tag 1 keinen strengen Rahmen dafür gab. Im großen Schema der Dinge sind nicht abtötbare Prozesse äußerst selten (man merkt es nicht, wenn sie nicht stattfinden) ). Es ist ein Symptom für Buggy-Fahrer. Beim Schreiben von Linux-Treibern wurde ein begrenzter Aufwand betrieben. Um mehr Fälle von längerem ununterbrochenem Schlaf zu vermeiden, müssten entweder mehr Personen für die Aufgabe eingesetzt werden, oder es würde zu weniger unterstützter Hardware und schlechterer Leistung führen.

Gilles 'SO - hör auf böse zu sein'
quelle
Das Problem liegt also teilweise bei Treibern, die NFS-Laufwerke verarbeiten. Ist das korrekt? Wenn NFS-Treiber keine Antwort vom Server erhalten, können sie die Ressourcen selbst freigeben und einen Fehler zurückgeben, anstatt ewig zu warten. Nehmen wir aus der Sicht des Kernels an, er hat tatsächlich nur den Speicher freigegeben, auf den möglicherweise das Peripheriegerät zugreifen wird. Was würde passieren? Kernel-Absturz? Unzulässiger Speicherzugriff? Würde sich der Kernel davon erholen können?
Genom