fork () e come i segnali vengono inviati ai processi


13

Programmo che ho scritto in C fork () è un processo figlio. Nessuno dei due processi terminerà. Se lancio il programma dalla riga di comando e premo control-c quale processo (i) riceverà il segnale di interruzione?

Risposte:


20

Perché non lo proviamo e vediamo? Ecco un programma banale che utilizza signal(3)per intercettare SIGINTsia il processo padre che figlio e stampare un messaggio che identifica il processo quando arriva.

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

Chiamiamolo così test.c. Ora possiamo eseguirlo:

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

I segnali di interruzione generati nel terminale vengono inviati al gruppo di processo attivo, che qui include sia padre che figlio . Si può vedere che sia child_trape parent_trapsono stati giustiziati quando ho premuto Ctrl- C.

C'è una lunga discussione sulle interazioni tra forke segnali in POSIX . La parte più materiale qui è che:

Un segnale inviato al gruppo di processi dopo il fork () deve essere consegnato sia al genitore che al figlio.

Notano anche che alcuni sistemi potrebbero non comportarsi esattamente nel modo corretto, in particolare quando il segnale arriva molto vicino al tempo di fork(). Capire se stai usando uno di quei sistemi probabilmente richiederà la lettura del codice o molta fortuna, perché le interazioni sono vanamente improbabili in ogni singolo tentativo.

Altri punti utili sono che:

  • Un segnale generato manualmente e inviato a un singolo processo (forse con kill) verrà consegnato solo a quel processo, indipendentemente dal fatto che sia il genitore o il figlio.
  • L'ordine in cui i gestori del segnale eseguono tra i processi non è definito, quindi non è possibile fare affidamento prima su nessuno dei due.
  • Se non si definisce un gestore di interrupt (o si ignora esplicitamente il segnale), entrambi i processi uscirebbero semplicemente con un SIGINTcodice (comportamento predefinito).
  • Se uno gestisce il segnale in modo non fatale e l'altro no, quello senza il gestore morirà e l'altro continuerà.

Presumo che le shell possano anche interferire in modi interessanti? Se è un segnale che possono intrappolare, potrebbe inviarlo ai suoi figli? (E poi c'è SIGHUP) (Tutto ciò potrebbe significare che mentre il sistema operativo non invia i segnali, un processo figlio potrebbe non essere influenzato da un segnale al genitore ...)
Gert van den Berg
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.