fork () et comment les signaux sont transmis aux processus

13

Je programme que j'ai écrit en C fork () hors d'un processus enfant. Aucun des deux processus ne prendra fin. Si je lance le programme à partir de la ligne de commande et appuie sur Ctrl-c, quel (s) processus recevra le signal d'interruption?

Neil Locketz
la source

Réponses:

20

Pourquoi ne l'essayons-nous pas et voyons-nous? Voici un programme trivial qui utilise signal(3)pour intercepter SIGINTle processus parent et enfant et imprimer un message identifiant le processus à son arrivée.

#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;
}

Appelons ça test.c. Maintenant, nous pouvons l'exécuter:

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

Les signaux d'interruption générés dans le terminal sont fournis au groupe de processus actif, qui comprend ici à la fois le parent et l'enfant . Vous pouvez voir que les deux child_trapet parent_trapont été exécutés quand je pressais Ctrl- C.

Il y a une longue discussion sur les interactions entre forket les signaux dans POSIX . La partie la plus importante ici est que:

Un signal envoyé au groupe de processus après le fork () doit être envoyé au parent et à l'enfant.

Ils notent également que certains systèmes peuvent ne pas se comporter exactement de la bonne manière, en particulier lorsque le signal arrive très près de l'heure de la fork(). Déterminer si vous êtes sur l'un de ces systèmes nécessitera probablement la lecture du code ou beaucoup de chance, car les interactions sont peu probables à chaque tentative individuelle.

D'autres points utiles sont les suivants:

  • Un signal généré manuellement et envoyé à un processus individuel (peut-être avec kill) ne sera délivré qu'à ce processus, qu'il s'agisse du parent ou de l'enfant.
  • L'ordre dans lequel les gestionnaires de signaux s'exécutent entre les processus n'est pas défini, vous ne pouvez donc pas compter sur l'un ou l'autre en premier.
  • Si vous ne définissez pas de gestionnaire d'interruption (ou ignorez explicitement le signal), les deux processus se termineraient simplement avec un SIGINTcode (le comportement par défaut).
  • Si l'un gère le signal de manière non fatale et que l'autre ne le fait pas, celui sans le gestionnaire mourra et l'autre continuera.
Michael Homer
la source
Je suppose que les obus peuvent également interférer de manière intéressante? S'il s'agit d'un signal qu'ils peuvent piéger, pourrait-il l'envoyer à ses enfants? (Et puis il y a SIGHUP) (Tout cela pourrait signifier que même si le système d'exploitation n'envoie pas les signaux, un processus enfant peut ne pas être affecté par un signal envoyé au parent ...)
Gert van den Berg