Будет ли ctrl+c посылать сигналы SIGINT как родительским, так и дочерним процессам в Linux?
В терминале я выполнил основной родительский процесс, который разветвляет дочерний процесс. В обоих родительских и дочерних процессах я реализовал обработчик сигналов SIGINT. Итак, когда я нажимаю "ctrl+c", оба обработчика будут вызваны одновременно? Или мне нужно вызвать обработчик сигнала дочернего процесса явно в обработчике родительского процесса?
Я посмотрел этот пост: Как Ctrl-C завершает дочерний процесс? который говорит, что " сигнал SIGINT генерируется дисциплина терминальной линии и широковещательная передача всем процессам в группе процессов переднего плана терминала". Я просто не совсем понял, что означает "группа процессов переднего плана".
Спасибо,
2 ответа:
Как в Родительском, так и в дочернем процессах я реализовал сигнал SIGINT обработчик. Поэтому, когда я нажимаю "ctrl+c", оба обработчика будут вызваны по адресу в одно и то же время?
Да, они оба будут получать
SIGINT
.Или мне нужно вызвать обработчик сигнала дочернего процесса явно в обработчик родительского процесса?
"вызов" обработчика сигналов другого процесса не имеет смысла. Если оба процесса имеют установленный обработчик, то они будут вызывается, как только они получают сигнал
SIGINT
.Как правило, процесс, связанный с управляющим терминалом, является процессом переднего плана,а его группа процессов называется группой процессов переднего плана. когда вы запускаете процесс из командной строки, это процесс переднего плана:Я просто не совсем понял, что делает " группа процессов переднего плана" средства.
Например
$ ./script.sh # foreground process $ ./script & # background process
Я предлагаю вам прочитать о
tty
и ещеThe TTY demystified
для детального объяснение.
Это иллюстрирует, как сигнал действительно передается ребенку, если ребенок не изменил свою группу процессов.
setpgid
минимальный пример группы процессов POSIX CГлавная.с:
#define _XOPEN_SOURCE 700 #include <assert.h> #include <signal.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> void signal_handler(int sig) { char sigint_str[] = "sigint\n"; if (sig == SIGINT) { write(STDOUT_FILENO, sigint_str, sizeof(sigint_str)); } signal(sig, signal_handler); } int main(int argc, char **argv) { (void)(argv); pid_t pid, pgid; signal(SIGINT, signal_handler); signal(SIGUSR1, signal_handler); pid = fork(); assert(pid != -1); if (pid == 0) { /* Change the pgid. * The new one is guaranteed to be different than the previous, which was equal to the parent's, * because `man setpgid` says: * > the child has its own unique process ID, and this PID does not match * > the ID of any existing process group (setpgid(2)) or session. */ if (argc == 1) { setpgid(0, 0); } printf("child pid, pgid = %ju, %ju\n", (uintmax_t)getpid(), (uintmax_t)getpgid(0)); assert(kill(getppid(), SIGUSR1) == 0); while (1); exit(EXIT_SUCCESS); } /* Wait until the child sends a SIGUSR1. */ pause(); pgid = getpgid(0); printf("parent pid, pgid = %ju, %ju\n", (uintmax_t)getpid(), (uintmax_t)pgid); /* man kill explains that negative first argument means to send a signal to a process group. */ kill(-pgid, SIGINT); while (1); }
Компиляция и запуск:
gcc -g -std=c99 -Wall -Wextra -o setpgid setpgid.c -lpthread ./setpgid
Результат:
child pid, pgid = 28250, 28249 parent pid, pgid = 28249, 28249 sigint sigint
И программа зависает.
Pgid обоих процессов один и тот же, так как он наследуется через
fork
.Затем, если вы нажмете:
Ctrl + C
Он выводит снова:
sigint sigint
Это hows how:
- послать сигнал всей группе процессов с помощью
kill(-pgid, SIGINT)
- Ctrl + C на терминале посылает kill всей группе процессов по умолчанию
Если вы работаете с аргументом, например:
./setpgid 1
Ребенок меняет свой pgid, и теперь каждый раз печатается только один sigint: родительская.
Выйти из программы, отправив другой сигнал процессам, например SIGQUIT с
Ctrl + \
.Если вы изменили идентификатор дочерней группы однако тогда он также не получит этот SIGQUIT, и вы должны убить его явно:
Это позволяет понять, почему сигнал посылается всем процессам по умолчанию: в противном случае мы получили бы кучу процессов, оставшихся для очистки вручную.ps aux | grep setpgid kill -9 $PID
Протестировано на Ubuntu 18.04. GitHub вверх по течению .