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:
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?
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 .
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.
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:
NLMSG_DONE
proc_event_header.what
Wert von PROC_EVENT_EXIT
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.
Ein vollständiges Codebeispiel ist hier .