Überwachen Sie, ob ein Prozess in C beendet wurde

7

Einführung

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%

Was ich versucht habe

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.

Die Frage

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?

    
0x450 27.07.2015, 16:36
quelle

4 Antworten

12

Wenn Sie WNOHANG an waitpid übergeben, sollte es nicht blockieren.

%Vor%     
Eric Renouf 27.07.2015, 16:39
quelle
11

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.

    
Basile Starynkevitch 27.07.2015 16:42
quelle
6

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.

    
Bruce Ediger 27.07.2015 17:18
quelle
5

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:

  • Das Lesen von der Pipe wartet auf das Kind und alle seine Kinder, um zu beenden (es sei denn, einige von ihnen schließen den Dateideskriptor davor).
  • Es ist möglich, dass mehrere Prozesse von demselben Dateideskriptor gelesen werden, was dazu führt, dass alle auf denselben Prozess (oder dieselben Prozesse) warten, bis sie beendet werden.
  • Sie können nicht darauf warten, dass ein Kind beendet wird. Mit dieser Methode können Sie auch auf das Beenden eines Elternteils oder eines Geschwisters warten.
  • Durch die Verwendung von close on exec können Sie darauf warten, dass ein Prozess beendet wird oder einen execve Systemaufruf erfolgreich ausführt.
  • Sie können den Systemaufruf select oder poll für die Pipe zusammen mit anderen Dateideskriptoren verwenden.
kasperd 27.07.2015 21:51
quelle

Tags und Links