Если процесс запускает другие процессы, он обычно хочет отслеживать их состояние.
Когда дочерний процесс завершается, он почти полностью исчезает. Он превращается в процесс зомби, и для другого процесса (обычно родительского) хранится достаточно информации, чтобы почему прекратил (в основном, его код возврата).
Затем, когда родитель успешно выполняет wait
для дочернего элемента, возвращается код возврата и очищаются последние остатки дочернего элемента.
И у родителя нет , чтобы сделать это. Есть способы запустить дочерний процесс, в котором родительский процесс будет изменен, вы можете увидеть разницу между:
sleep 3601 &
( sleep 3602 & )
Последний запускает дочернюю оболочку и, начиная с нее, запускает сон, затем дочерняя оболочка завершается, так что дочерний элемент получает новый родитель:
1 /sbin/init splash
|
+-- 1121 /usr/sbin/lightdm
|
+-- 1846 /usr/sbin/lightdm --session-child 12 19
|
+-- 2078 /sbin/upstart --user
|
+--- 29899 sleep 3602
|
+--- 2929 /usr/lib/gnome-terminal/gnome-terminal-server
|
+--- 2935 bash (my bash shell)
|
+--- 29891 sleep 3601
Здесь вы можете видеть, что один из sleep
процессов по-прежнему имеет мою оболочку в качестве родителя, но другой был перемещен вверх по дереву процессов до upstart
.
Зачастую он принимается init
(a) , который имеет код специально для того, чтобы пожинать зомби (wait
- нажимая на них, затем выбрасывая код возврата).
(a) Современные UNIX могут переопределить это с помощью вызова prctl()
с аргументом PR_SET_CHILD_SUBREAPER
. Это помечает процесс как подчиненный.
Затем, когда родитель умирает, суб-жнец первого кулака при переходе вверх по дереву процессов становится новым родителем его непосредственных потомков (с init
, являющимся конечным жнецом).
На самом деле вы можете увидеть это в приведенном выше дереве процессов, где очевидно, что upstart
сделал именно это. Это означает, что it был первым суб-жнецом, найденным при ходьбе по дереву, поэтому sleep
, принадлежавший процессу, который умер, не достигал вплоть до init
.