Будет ли 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 вверх по течению .