Я уже довольно давно изучаю поведение ядра Linux, и мне всегда было ясно, что:
Когда процесс умирает, все его дочерние элементы возвращаются
init
процессу (PID 1) до тех пор, пока они в конечном итоге не умрут.
Однако недавно кто-то с большим опытом работы с ядром сказал мне, что:
Когда процесс завершается, все его дочерние элементы также умирают (если вы не используете,
NOHUP
в этом случае они возвращаютсяinit
).
Теперь, хотя я не верю в это, я все же написал простую программу, чтобы убедиться в этом. Я знаю, что не следует полагаться на time ( sleep
) для тестов, поскольку все зависит от планирования процессов, но для этого простого случая, я думаю, этого достаточно.
int main(void){
printf("Father process spawned (%d).\n", getpid());
sleep(5);
if(fork() == 0){
printf("Child process spawned (%d => %d).\n", getppid(), getpid());
sleep(15);
printf("Child process exiting (%d => %d).\n", getppid(), getpid());
exit(0);
}
sleep(5);
printf(stdout, "Father process exiting (%d).\n", getpid());
return EXIT_SUCCESS;
}
Вот вывод программы, с ассоциированным ps
результатом каждый раз, когда printf
говорит:
$ ./test &
Father process spawned (435).
$ ps -ef | grep test
myuser 435 392 tty1 ./test
Child process spawned (435 => 436).
$ ps -ef | grep test
myuser 435 392 tty1 ./test
myuser 436 435 tty1 ./test
Father process exiting (435).
$ ps -ef | grep test
myuser 436 1 tty1 ./test
Child process exiting (436).
Теперь, как вы можете видеть, это ведет себя так, как я и ожидал. Сиротский процесс (436) возвращается к init
(1), пока он не умрет.
Однако существует ли система на основе UNIX, к которой это поведение не применяется по умолчанию? Существует ли какая-либо система, в которой смерть процесса немедленно вызывает смерть всех его детей?
nohup
сdisown
.disown
является встроенной в некоторую оболочку, которая удаляет запущенное задание из таблицы заданий (принимая аргумент, подобный этому%1
), и основной полезный побочный эффект этого заключается в том, что оболочка не отправляет SIGHUP подпроцессу.nohup
это внешняя утилита, которая игнорирует SIGHUP (и делает несколько других вещей), а затем запускает команду, переданную в ее командной строке.nohup
, он игнорирует сигнал передexec
командой.Это правильно, если процесс является лидером сеанса. Когда лидер сеанса умирает, SIGHUP отправляется всем участникам этого сеанса. На практике это означает, что его дети и их потомки.
Процесс делает себя лидером сессии, вызывая
setsid
. Снаряды используют это.источник
fork
, уничтожить родительский процессsetsid
) и разбудил другого ребенка в этот новый сеанс. Однако, когда родительский процесс (новый лидер сеанса) умер, ребенок не получил SIGHUP и привязывался к нему,init
пока в конце концов не завершился.setpgid(2)
man-страницы: Если у сеанса есть управляющий терминал, и флаг CLOCAL для этого терминала не установлен, и происходит зависание терминала, то лидеру сеанса отправляется SIGHUP. Если лидер сеанса выходит, то сигнал SIGHUP также будет отправляться каждому процессу в группе процессов переднего плана управляющего терминала.Таким образом, вышеприведенные плакаты говорят о том, что дети не умирают, родитель убивает их (или посылает им сигнал, по которому они заканчивают). Таким образом, вы можете получить то, о чем просите, если вы запрограммируете Родителя (1) вести учет всех его дочерних элементов и (2) отправлять сигнал всем его дочерним элементам.
Это то, что делает Shell, и это должно быть тем, что делает ваш родительский процесс. Может потребоваться перехватить сигнал HUP в родительском элементе, чтобы у вас все еще было достаточно контроля, чтобы убить дочерних элементов.
источник
Я упускаю один бит в ответах, которые немного связаны с умирающими родителями: когда процесс пишет в канале, для которого больше нет процесса чтения, он получает SIGPIPE. Стандартное действие для SIGPIPE - завершение.
Это действительно может привести к смерти процессов. Фактически, это стандартный способ
yes
смерти программы .Если я выполню
в моей системе ответ
и 141 действительно 128 + SIGPIPE:
от
man 7 signal
.источник