Wie man richtig darauf wartet, dass ein Ereignis / Prozess nicht mehr der Elternteil ist?

9

Ich verwende GO , um zu prüfen, ob ein Prozess (nicht übergeordnet) beendet wurde, im Grunde genommen etwas wie pwait Kommando in FreeBSD , aber geschrieben in go.

Momentan versuche ich ein for loop mit einem kill -0 , aber ich stelle fest, dass die CPU-Auslastung bei diesem Ansatz sehr hoch ist 99% , hier ist der Code:

%Vor%

Irgendeine Idee, wie man das verbessert oder richtig umsetzt.

Vielen Dank im Voraus.

AKTUALISIEREN

Das Hinzufügen eines sleep innerhalb der Schleife wie vorgeschlagen, hilft die Last zu reduzieren.

Von den bereitgestellten Links scheint es möglich zu sein, an die vorhandene PID anzuhängen, ich werde versuchen PtraceAttach aber wissen Sie nicht, ob dies Nebenwirkungen haben kann, keine Ahnung?

Wie vorgeschlagen, konnte ich kqueue verwenden:

%Vor%

Funktioniert gut, aber frage mich, wie man dasselbe unter Linux implementieren / erreichen kann, da ich glaube, dass kqueue nicht darauf verfügbar ist, irgendwelche Ideen?

    
nbari 01.07.2016, 20:18
quelle

1 Antwort

1

Eine Lösung wäre die Verwendung des Netlink-Proc-Connectors, bei dem es sich um einen Socket handelt, den der Kernel verwendet, um Userspace über verschiedene Prozessereignisse zu informieren. Die offizielle Dokumentation fehlt etwas, obwohl es ein paar gute Beispiele in C, die wahrscheinlich besser zu lesen sind.

Der Hauptgrund für die Verwendung des proc-Konnektors ist, dass der Prozess als root ausgeführt werden muss. Wenn Sie Ihr Programm als Benutzer ohne Rootberechtigung ausführen, sollten Sie andere Optionen in Betracht ziehen, z. B. das periodische Abfragen von /proc auf Änderungen. Jeder Ansatz, der Polling verwendet, wie andere darauf hingewiesen haben, ist anfällig für eine Race-Bedingung, wenn der Prozess beendet wird und ein anderer zwischen Polls mit der gleichen PID gestartet wird.

Um den proc-Konnektor in Go zu verwenden, müssen wir etwas von C übersetzen. Insbesondere müssen wir die Strukturen proc_event und exit_proc_event von cn_proc.h , und die cn_msg und cb_id Strukturen von connector.h .

%Vor%

Wir müssen auch einen Netlink-Socket und eine Verbindungsbindung herstellen.

%Vor%

Als nächstes müssen wir die Nachricht PROC_CN_MCAST_LISTEN an den Kernel senden, um mitzuteilen, dass wir Ereignisse empfangen wollen. Wir können dies direkt aus C importieren, wo es als Aufzählung definiert ist, um ein wenig Tipparbeit zu sparen, und es in eine Funktion einfügen, da wir es mit PROC_CN_MCAST_IGNORE erneut aufrufen müssen, wenn wir die Daten vom Kernel erhalten haben.

%Vor%

Nachdem wir den Kernel wissen lassen, dass wir bereit sind, Ereignisse zu empfangen, können wir sie auf dem Sockel empfangen, an dem wir erstellt wurden. Sobald wir sie erhalten haben, müssen wir sie analysieren und nach relevanten Daten suchen. Wir kümmern uns nur um Nachrichten, die die folgenden Kriterien erfüllen:

  • Komm vom Kernel
  • Haben Sie einen Kopftyp von NLMSG_DONE
  • Habe einen proc_event_header.what Wert von PROC_EVENT_EXIT
  • Entspricht unserer PID

Wenn sie diese Kriterien erfüllen, können wir die relevanten Prozessinformationen in eine proc_event_exit struct extrahieren, die die PID des Prozesses enthält.

%Vor%

Ein vollständiges Codebeispiel ist hier .

    
PeterMalmgren 10.02.2017 21:15
quelle

Tags und Links