Использует waitpid или sigaction? - PullRequest
       1

Использует waitpid или sigaction?

7 голосов
/ 23 января 2012

Я понял, что: 1) waitpid используется для ожидания смерти ребенка, а затем для получения SIGCHLD и статуса выхода ребенка и т. Д. 2) Когда у нас есть обработчик сигнала для SIGCHLD, мы делаем еще несколько вещей, связанных с очисткой дочерних или других вещей (вплоть до программиста), а затем делаем waitpid, чтобы ребенок не пошел зомби, а затем вернулся.

Теперь, должны ли мы иметь и 1 и 2 в наших программах, когда мы делаем fork / exec и потомок возвращается? Если у нас есть оба, SIGCHLD получается первым, поэтому сначала вызывается обработчик сигнала, и, следовательно, успешно вызывается его waitpid, а не waitpid в коде родительского процесса, как показано ниже:

my_signal_handler_for_sigchld
{
do something
tmp = waitpid(-1,NULL,0);
print tmp (which is the correct value of the child pid)
}

int main ()
{
  sigaction(SIGCHLD, my_signal_handler_for_sigchld)
  fork()
  if (child) //do something, return
  if parent // waitpid(child_pid, NULL,0); print value returned from this waitpid - it is -1
}

Ценю, если кто-то поможет мне понять это.

Ответы [ 2 ]

19 голосов
/ 23 января 2012

Вам действительно не нужно обрабатывать SIGCHLD, если вы намереваетесь запустить дочерний процесс, сделайте что-нибудь, а затем дождитесь его завершения. В этом случае вы просто звоните waitpid, когда будете готовы к синхронизации. Единственная вещь, для которой SIGCHLD полезна, - это асинхронное уведомление о дочернем завершении, например, если у вас есть интерактивное (или долго работающий демон) приложение, которое порождает различных дочерних элементов и должно знать, когда они закончат работу. Тем не менее, SIGCHLD действительно плохо / уродливо и для этой цели, так как, если вы используете библиотечный код, который создает дочерние процессы, вы можете перехватывать события для дочерних библиотек, завершающих работу, и мешать их обработке. Обработчики сигналов по своей природе глобальны для процессов и имеют дело с глобальным состоянием, которое обычно представляет собой A Bad Thing (tm).

Вот два лучших подхода, когда у вас есть дочерние процессы, которые будут завершаться асинхронно:

Подход 1 (select / poll на основе событий): убедитесь, что у вас есть канал к / от каждого дочернего процесса, который вы создаете. Это может быть либо их stdin / stdout / stderr, либо просто дополнительный фиктивный fd. Когда дочерний процесс завершается, его конец канала будет закрыт, и ваш главный цикл обработки событий обнаружит активность этого дескриптора файла. Из того факта, что он закрылся, вы узнаете, что дочерний процесс умер, и позвоните waitpid, чтобы пожать зомби.

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

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

1 голос
/ 23 января 2012

Вам нужно вызывать ожидающие системные вызовы, такие как waitpid или друзья -eg wait4 и т. Д., Иначе у вас может быть процессов зомби .

Вы можете обработать SIGCHLD чтобы получить уведомление о том, что какой-то дочерний элемент закончился (или остановился и т. Д.), Но вам нужно будет подождать его позже.

Обработчики сигналов ограничены для вызова небольшого набора async-signal-safe-функции (см. сигнал (7) для более).Хороший совет - просто установить флаг volatile sig_atomic_t внутри и проверить его позже и в более безопасных местах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...