fork () und wie Signale an Prozesse geliefert werden

13

Ich programmiere, dass ich in C fork () 's aus einem Child-Prozess geschrieben habe. Keiner der Prozesse wird beendet. Wenn ich das Programm von der Kommandozeile aus starte und Control-C drücke, welche Prozesse erhalten das Interrupt-Signal?

Neil Locketz
quelle

Antworten:

20

Warum probieren wir es nicht aus und sehen? Hier ist ein einfaches Programm mitsignal(3) , um SIGINTsowohl den übergeordneten als auch den untergeordneten Prozess abzufangen und eine Nachricht auszudrucken, die den Prozess identifiziert, wenn er eintrifft.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void parent_trap(int sig) {fprintf(stderr, "They got back together!\n");}
void child_trap(int sig) {fprintf(stderr, "Caught signal in CHILD.\n");}
int main(int argc, char **argv) {
    if (!fork()) {
        signal(SIGINT, &child_trap);
        sleep(1000);
        exit(0);
    }
    signal(SIGINT, &parent_trap);
    sleep(1000);
    return 0;
}

Nennen wir das test.c . Jetzt können wir es ausführen:

$ gcc test.c
$ ./a.out
^CCaught signal in CHILD.
They got back together!

Im Terminal erzeugte Interrupt-Signale werden an die aktive Prozessgruppe weitergeleitet, die hier sowohl übergeordnet als auch untergeordnet ist . Sie können das beide child_trapund sehenparent_trap ausgeführt wurden , als ich gedrückt Ctrl- C.

Es gibt eine lange Diskussion über Wechselwirkungen zwischenfork und Signalen in POSIX . Das Wesentlichste dabei ist:

Ein Signal, das an die Prozessgruppe nach dem fork () gesendet wird, sollte sowohl an das übergeordnete als auch an das untergeordnete Element gesendet werden.

Sie stellen außerdem fest, dass sich einige Systeme möglicherweise nicht genau richtig verhalten, insbesondere, wenn das Signal sehr nahe an der Uhrzeit des eintrifft fork() . Um herauszufinden, ob Sie sich auf einem dieser Systeme befinden, müssen Sie wahrscheinlich den Code lesen oder viel Glück haben, da die Interaktionen bei jedem einzelnen Versuch unwahrscheinlich sind.

Andere nützliche Punkte sind:

  • Ein Signal, das manuell generiert und an einen einzelnen Prozess (möglicherweise mit kill) gesendet wird, wird nur an diesen Prozess gesendet , unabhängig davon, ob es sich um den übergeordneten oder den untergeordneten Prozess handelt.
  • Die Reihenfolge, in der die Signalhandler zwischen Prozessen ausgeführt werden, ist nicht definiert, sodass Sie sich nicht darauf verlassen können, dass beide zuerst ausgeführt werden.
  • Wenn Sie keinen Interrupt-Handler definieren (oder das Signal explizit ignorieren), werden beide Prozesse nur mit einem SIGINTCode beendet (Standardverhalten).
  • Wenn einer das Signal nicht tödlich behandelt und der andere nicht, stirbt der eine ohne den Handler und der andere fährt fort.
Michael Homer
quelle
Ich nehme an, Muscheln können auch auf interessante Weise stören? Wenn es ein Signal ist, das sie fangen können, könnte es es an seine Kinder senden? (Und dann gibt es SIGHUP.) (All dies kann bedeuten, dass das Betriebssystem zwar keine Signale sendet, ein untergeordneter Prozess jedoch möglicherweise nicht von einem Signal an den übergeordneten Prozess unberührt bleibt.)
Gert van den Berg