Как проверить, является ли процесс с pid X зомби?

Я получил PID процесса, и мне нужно проверить, не является ли он зомби, используя системные вызовы POSIX в C. Как мне это сделать?

Проблема, с которой я сталкиваюсь, заключается в том, что у меня есть процесс, и он разветвляется на множество дочерних процессов, все дочерние элементы выполняют exec, и иногда я хочу выполнять exec в фоновом режиме, поэтому я не могу действительно ждать () дочерних процессов, которые идут в фоновом режиме. Я мог бы периодически ждать() (один раз в моем основном цикле), но мне нужно знать, какие процессы являются зомби, чтобы мой отцовский процесс не зависал в ожидании детей, которые не скоро закончатся.

Если вам интересно, я создаю оболочку unix, и в природе оболочки дочерние процессы ведут себя асинхронно.


person Hoffmann    schedule 24.10.2009    source источник


Ответы (5)


Вы не можете проверить, является ли процесс зомби, с помощью чистых вызовов POSIX, за исключением случаев, когда вы являетесь родительским процессом и пожинаете его с помощью wait семейный звонок. Так что вам придется найти хорошее место, чтобы ждать ребенка.

Один из вариантов — установить обработчик SIGCHLD и выполнить там waitpid(0, &status, WNOHANG). Обязательно зацикливайте до тех пор, пока он не перестанет находить какие-либо процессы - если двое детей умрут в течение короткого промежутка времени, вы можете получить только один SIGCHLD.

Другим вариантом является двойная вилка, то есть fork(), чтобы дочерний элемент (назовем его дочерним элементом A) снова разветвлялся, чтобы второй дочерний элемент (дочерний элемент B) выполнялся. Затем ребенок А немедленно выходит. В то же время родитель wait()ing для ребенка A. Как только ребенок A ушел, процесс инициализации системы позаботится о дочернем B, когда он в конечном итоге умрет. Этот метод проще, но ваша оболочка не сможет узнать, когда ребенок B умрет, поэтому, если вам нужна эта информация, используйте первый метод.

person bdonlan    schedule 24.10.2009
comment
Спасибо, я использую ваше первое предложение. Ваше второе предложение также интересно, но было бы слишком сложно реализовать его и, вероятно, снизить производительность из-за двойного разветвления. - person Hoffmann; 25.10.2009
comment
Разветвление выполняется очень быстро на многих (большинстве?) современных Unix-подобных системах, и используется множество трюков (это хлеб с маслом для ядра). Пожалуйста, не оценивайте его как медленное без анализа производительности. - person ; 25.10.2009

Но… но… зомби — это дочерний элемент (на каком-то уровне), а проверяющий процесс — родитель, верно? Итак, если вы обеспокоены тем, что конкретный pid является зомби, почему бы просто не сделать waitpid(2) с WNOHANG и избавиться от него? Теперь это будет потреблять статус выхода, поэтому может быть плохой идеей, если какой-то другой процесс действительно захочет wait в будущем.

person DigitalRoss    schedule 24.10.2009
comment
Спасибо, я не знал, что ожидание может немедленно вернуться с этой опцией (кстати, это WNOHANG). - person Hoffmann; 25.10.2009

Вы упомянули, что строите оболочку Unix; вы должны прочитать это: Правильная обработка SIGINT/SIGQUIT

person Teddy    schedule 24.10.2009
comment
Интересная бумага. Я задаюсь вопросом, работает ли emacs в полуготовом режиме, когда нажатия клавиш все еще генерируют сигналы; большинство программ на основе curses запускаются с настройками терминала в необработанном режиме, и в этом случае драйвер терминала не генерирует для программы сигналов SIGINT или SIGQUIT; программа просто получает нажатия клавиш, как и любой другой управляющий символ. - person Jonathan Leffler; 09.11.2009
comment
Emacs действительно получает сигналы от нажатия клавиш. Он также переназначает C-g (^G) в качестве ключа для SIGINT, и, как я проверял, он делает некоторые действительно неприятные непереносимые длинные переходы обработчиков сигналов вне сигнала... - person R.. GitHub STOP HELPING ICE; 03.07.2010

Обычно оболочка проверяет несуществующие дочерние элементы незадолго до вывода приглашения, используя системный вызов waitpid(2) и параметр WNOHANG, как уже обсуждалось. Вам также может понадобиться обработчик SIGCHLD, но вам придется решить, что вы собираетесь делать с информацией, если вы заняты ожиданием завершения какого-либо процесса переднего плана, а на самом деле завершается фоновый процесс.

Это лишь незначительная вариация выбранного в данный момент ответа.

person Jonathan Leffler    schedule 25.10.2009

А как насчет команды оболочки «ps», которая показывает вам таблицу активных процессов, где вы можете найти, что процесс «несуществующий»? Я полагаю, должен быть способ получить эту информацию из кода C.

person Yegor Dubinker    schedule 15.12.2014
comment
Я полагаю, вы могли бы использовать вызов system() и проанализировать результат, но это будет зависеть от платформы (а также зависит от системы, в которой установлена ​​команда ps, что не гарантируется). Программа ps не является частью спецификации POSIX. Кроме того, вызов внешней программы будет включать в себя синтаксический анализ строки и разветвление другого процесса, что будет очень медленным и очень уродливым. - person Hoffmann; 29.12.2014