Я копаюсь в разных источниках, но не могу найти хорошее описание анатомии пожинающих детей. Это простой случай того, что я хотел бы понять.
$ cat <( sleep 100 & wait ) &
[1] 14247
$ ps ax -O pgid | grep $$
12126 12126 S pts/17 00:00:00 bash
14248 12126 S pts/17 00:00:00 bash
14249 12126 S pts/17 00:00:00 sleep 100
14251 14250 S pts/17 00:00:00 grep --color=auto 12126
$ kill -2 14248
$ ps ax -O pgid | grep $$
12126 12126 S pts/17 00:00:00 bash
14248 12126 Z pts/17 00:00:00 [bash] <defunct>
14249 12126 S pts/17 00:00:00 sleep 100
14255 14254 S pts/17 00:00:00 grep --color=auto 12126
Почему зомби ждут ребенка?
Вы можете объяснить это? Нужно ли мне знать C и читать исходный код Bash, чтобы получить более полное представление об этом, или есть какая-либо документация? Я уже консультировался:
- различные ссылки на этом сайте и переполнение стека
- Командная строка Linux от W. Shotts
man bash
- Справочное руководство по Bash (в документации по исходному коду Bash)
- Руководство по Bash для начинающих @ tldp.org
- Расширенное руководство по написанию сценариев
GNU bash, версия 4.3.42 (1) -релиз (x86_64-pc-linux-gnu)
Linux 4.4.0-31-generic # 50-Ubuntu SMP Ср 13 июля 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux
Ответы:
Зомби не ждет своего ребенка. Как и любой процесс зомби, он остается, пока его родитель не соберет его.
Вы должны отобразить все вовлеченные процессы, чтобы понять, что происходит, а также посмотреть на PPID. Используйте эту командную строку:
Родитель процесса, который вы убиваете
cat
. В результате bash запускает фоновую командуcat <( sleep 100 & wait )
в подоболочке. Поскольку единственное, что делает этот подоболочка, это настроить некоторое перенаправление и затем выполнить внешнюю команду, эта подоболочка заменяется внешней командой. Вот краткое изложение:fork
выполнение фоновой командыcat <( sleep 100 & wait )
в дочернем элементе (14247).pipe
создание канала, а затемfork
создает дочерний элемент для запуска процесса подстановкиsleep 100 & wait
.fork
бежатьsleep 100
в фоновом режиме. Поскольку внук не является интерактивным, фоновый процесс не выполняется в отдельной группе процессов. Затем внук ждетsleep
выхода.setpgid
(это фоновое задание в интерактивной оболочке, поэтому он получает свою собственную группу процессов), а затемexecve
запускаетсяcat
. (Я немного удивлен, что подстановка процессов не происходит в группе фоновых процессов.)cat
, который ничего не знает ни о каком дочернем процессе и не имеет деловых вызововwait
. Так как родитель внука не пожинает его, внук остается зомби.cat
завершается - либо потому, что вы его убили, либо потому, чтоsleep
возвращает и закрывает канал, чтобыcat
увидеть конец его ввода. В этот момент родитель зомби умирает, поэтому зомби собирается init, а init пожинает его.Если вы измените команду на
затем
cat
запускается в отдельном процессе, а не в дочернем элементе исходного процесса bash: первый дочерний элемент должен остаться позади, чтобы запуститьecho done
. В этом случае, если вы убьете внука, он не останется зомби, потому что ребенок (который все еще работает с bash) пожинает его.Смотрите также Как Linux справляется с процессом зомби и могут ли зомби иметь сирот? Будут ли потревожены дети-сироты, пожиная зомби?
источник
cat
), не ожидающим 14248 (ожиданиеsleep
)? Есть ли какая-то память о том, кто кого ждет, которого потерял ребенок (14247), а оригинальный bash (14246) не потерял, или, возможно, список сигналов, таких как SIGCHLD, о которых следует вызывать, и 14247 (в данный момент запущенныхbash
) отписался с помощью С уважением к 14248?wait
своего потомка, то есть пожинает его. Я вижу, как это может сбить с толку, я удалил это предложение, которое не было даже в нужном месте в хронологическом смысле. Информация о том, что процесс умер, переходит к его родителю, процесс не может «подписаться» на получение информации о смерти какого-либо другого процесса.Зомби не ждет ребенка. Вместо этого, зомби - это процесс, который уже умер (сам по себе или был убит - как в вашем примере), когда его код, данные и стек были освобождены, и теперь содержит только свой код выхода, ожидая, когда его родитель вызовет
wait(2)
его извлечение. (и, таким образом, окончательно очистить запись процесса полностью из таблицы процессов)В вашем примере, когда сон заканчивается (или убивается), родитель прочитает статусы выхода и пожнет зомби. Смотрите выше
wait(2)
для деталей.источник