fork () и как сигналы доставляются процессам

13

Я программирую, что я написал в C fork () от дочернего процесса. Ни один процесс не прекратится. Если я запустил программу из командной строки и нажал control-c, какой процесс (ы) получит сигнал прерывания?

Нил Локетц
источник

Ответы:

20

Почему бы нам не попробовать и посмотреть? Вот тривиальная программа, которая используется signal(3)для перехвата SIGINTкак родительского, так и дочернего процесса и распечатывает сообщение, идентифицирующее процесс, когда он прибывает.

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

Давайте назовем это test.c. Теперь мы можем запустить его:

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

Сигналы прерывания, генерируемые в терминале, доставляются в активную группу процессов, которая здесь включает в себя как родительский, так и дочерний процесс . Вы можете видеть, что оба child_trapи parent_trapбыли выполнены, когда я нажал Ctrl- C.

Существует долгое обсуждение взаимодействия forkи сигналов в POSIX . Наиболее существенная часть этого здесь - то, что:

Сигнал, отправляемый группе процессов после fork (), должен быть доставлен как родителю, так и потомку.

Они также отмечают, что некоторые системы могут вести себя не совсем корректно, в частности, когда сигнал поступает очень близко ко времени fork(). Выяснение того, находитесь ли вы в одной из этих систем, вероятно, потребует прочтения кода или большой удачи, поскольку в каждой отдельной попытке взаимодействия маловероятно маловероятны.

Другие полезные моменты:

  • Сигнал, созданный вручную и отправленный отдельному процессу (возможно, с помощью kill), будет доставлен только этому процессу, независимо от того, является ли он родительским или дочерним процессом.
  • Порядок, в котором обработчики сигналов выполняются между процессами, не определен, поэтому вы не можете полагаться ни на одно из первых.
  • Если вы не определяете обработчик прерываний (или явно игнорируете сигнал), оба процесса просто завершают работу с SIGINTкодом (поведение по умолчанию).
  • Если один обрабатывает сигнал не смертельно, а другой - нет, тот, у которого нет обработчика, умрет, а другой продолжит.
Майкл Гомер
источник
Я предполагаю, что снаряды также могут мешать интересным образом? Если это сигнал, который они могут заманить в ловушку, он может отправить его своим детям? (И затем есть SIGHUP) (Все это может означать, что, хотя ОС не отправляет сигналы, дочерний процесс не может быть затронут сигналом для родителя ...)
Герт ван ден Берг