Ich schreibe ein Überwachungsprogramm in C, das den Zyklus fork()
und exec()
ausführt. Ich muss jedoch überprüfen, ob der untergeordnete Prozess beendet wurde oder nicht, ohne den Hauptprozess, d. H. Das Überwachungsprogramm, zu blockieren. Etwas wie das:
Hauptprozess
%Vor%In Anbetracht der Tatsache, dass ich das Kind pid habe, habe ich Folgendes versucht:
Senden eines kill
Aufrufs mit signal 0
und Untersuchen von errno
:
if (kill(child_pid, 0) == -1 || errno == ESRCH)
, was meiner Meinung nach keine gute Möglichkeit ist, den Status des Kinderprozesses zu verfolgen, da es nicht vor den Rennbedingungen sicher ist. Außerdem hat es nicht funktioniert oder zumindest schien es so.
Überprüfung mit stat(2)
ob proc/child_pid
existiert. Alle oben genannten negativen Argumente sind auch in diesem Fall wahr und diese Methode ist langsamer.
waitpid(2)
. Leider blockiert es den Hauptprozess.
Gibt es eine andere Möglichkeit, diese Art von Informationen zu erhalten? Oder fehlt mir vielleicht etwas aus den Lösungen, die ich bereits ausprobiert habe?
Wenn Sie WNOHANG
an waitpid
übergeben, sollte es nicht blockieren.
Wenn ein Prozess beendet wird, können Sie den übergeordneten Prozess so einrichten, dass er ein SIGCHLD
-Signal erhält und verarbeitet, siehe Signal (7) ; Der Signalhandler kann nur async-signalsichere Funktionen aufrufen oder einen außerhalb des Handlers getesteten volatile sigatomic_t
-Flag setzen (z. B. in der Hauptereignisschleife um Umfrage (2) ...) oder schreibe (2) in einen Dateideskriptor (zB eine Pipe oder einige eventfd (2) ). Als Bruce Ediger antwortet können Sie auch das Linux-spezifische signalfd
verwenden.
Dann können Sie eine Wartefunktion verwenden, z. waitpid (2) (vielleicht mit WNOHANG
, wenn du nicht blocken willst ) oder wait4 (2) , um den Prozess abzuwarten und seinen Status usw. zu erhalten / p>
Lesen Sie auch Erweiterte Linux-Programmierung für mehr. Es gibt mehrere Kapitel zu diesen Fragen.
Wenn Sie möchten, dass Ihr Prozess nicht blockiert wird oder Sie andere Dateideskriptoren haben, sollten Sie sich die signalfd () Systemaufruf, wenn Sie für Linux schreiben.
Dieser Systemaufruf gibt einen speziellen Dateideskriptor zurück, den Sie in den Systemaufrufen select()
, poll()
und epoll()
verwenden können. Richtig eingerichtet, ein Child-Prozess beendet bewirkt, dass der Kernel den speziellen Dateideskriptor readabl erstellt. Das Lesen aus dem speziellen Dateideskriptor gibt Ihnen eine ausgefüllte Struktur mit Informationen über den Exit-Status des untergeordneten Prozesses.
Die Antwort von Basile Starynkevitch deckt die häufigsten Situationen ab.
Wenn Sie ungewöhnliche Situationen haben, kann es manchmal nützlich sein, eine Pipe zu verwenden. Erstellen Sie vor dem Erstellen des untergeordneten Prozesses eine Pipe mit dem Systemaufruf pipe
. Nach dem Erstellen des untergeordneten Prozesses schließen Sie das Schreibende der Pipe im übergeordneten Prozess. Das Lesen von der Pipe würde blockieren, bis das Kind beendet wird.
Dies unterscheidet sich von waitpid
auf folgende Weise:
execve
Systemaufruf erfolgreich ausführt. select
oder poll
für die Pipe zusammen mit anderen Dateideskriptoren verwenden. Tags und Links c monitoring process fork