waitpid, wnohang, wuntraced. Как я использую эти

Я немного смущен. Как я понимаю, waitpid с pid -1 означает, что я жду завершения всех дочерних процессов, но если я добавлю параметр к waitpid WNOHANG, этот параметр говорит о немедленном выходе, если ни один из них не завершился ... Это кажется чрезвычайно запутанным.

Почему я должен сказать компьютеру дождаться завершения дочерних процессов, а затем сразу после этого сказать ему немедленно выйти, если ни один из дочерних процессов не завершился?

Может ли кто-нибудь объяснить эту опцию и опции WUNTRACED? Я не знаю, что значит быть прослеженным.


person 8this    schedule 03.11.2015    source источник
comment
pid = -1 означает ожидание любого потомка, а не всех. А ожидание — это технический термин, относящийся к wait(2).   -  person melpomene    schedule 04.11.2015
comment
@melpomene Ах, да все очень разные. Спасибо за исправление. Скажем, у меня трое детей... как компьютер определяет, кого ждать? Или это первоначальный тип вещей, когда, если один из детей закончит, компьютер технически подождет и пойдет дальше?   -  person 8this    schedule 04.11.2015
comment
@8this Если вы передаете pid -1, он не ждет завершения всех дочерних элементов, он ждет завершения любого дочернего элемента. Как только любой ребенок закончил, его пожинают.   -  person fuz    schedule 04.11.2015


Ответы (2)


Если вы пройдете -1 и WNOHANG, waitpid() проверит, существуют ли дети-зомби. Если да, то один из них обрабатывается и возвращается его статус выхода. Если нет, то возвращается либо 0 (если существуют незавершенные дочерние процессы), либо возвращается -1 (если нет), а ERRNO устанавливается в ECHILD (нет дочерних процессов). Это полезно, если вы хотите узнать, умер ли недавно кто-либо из ваших детей, не дожидаясь смерти одного из них. Это довольно полезно в этом отношении.

Вариант WUNTRACED задокументирован так, как показано ниже, мне нечего добавить к этому описанию:

WUNTRACEDСостояние любых дочерних процессов, указанных в pid, которые остановлены и о состоянии которых еще не сообщалось с момента их остановки, также должно быть сообщено запрашивающему процессу.

Прочитайте страницу waitpid на POSIX для получения более подробной информации.

person fuz    schedule 03.11.2015

Обычно вы используете WNOHANG и WUNTRACED в разных случаях.

Случай 1. Предположим, у вас есть процесс, который порождает кучу дочерних процессов и должен делать другие вещи, пока дочерние процессы выполняются. Эти дочерние процессы иногда завершаются или уничтожаются, но ядро ​​будет удерживать их статус завершения до тех пор, пока какой-либо другой процесс не потребует его с помощью функций wait() или waitpid(). Таким образом, ваш родительский процесс должен время от времени вызывать wait()/waitpid(), чтобы позволить ядру избавиться от остатков дочернего процесса. Но мы не хотим, чтобы функция wait()/waitpid() блокировала, потому что в этом случае у нашего процесса есть другие задачи, которые ему нужно делать. Мы просто хотим получить статус мертвого процесса, если есть. Вот для чего нужен WNOHANG. Он предотвращает блокировку wait()/waitpid(), чтобы ваш процесс мог выполнять другие задачи. Если ребенок умер, его pid будет возвращен функцией wait()/waitpid(), и ваш процесс может действовать в соответствии с этим. Если ничего не умерло, то возвращаемый pid равен 0.

Случай 2. Предположим, что вместо этого ваш родительский процесс хочет ничего не делать, пока выполняются дочерние процессы. Вы не хотите, чтобы он просто выполнял цикл for, поэтому вы используете обычный wait()/waitpid() без WNOHANG. Ваш процесс выводится из очереди выполнения до тех пор, пока один из дочерних процессов не умрет. Но что, если один из ваших дочерних элементов остановлен с помощью SIGSTOP? Ваш ребенок больше не работает над задачей, которую вы ему поставили, но родитель все еще ждет. Таким образом, у вас есть тупик, в некотором смысле, если дочерний процесс не продолжается каким-то образом, внешним по отношению к вашему родителю и этому ребенку. WUNTRACED позволяет вашему родителю быть возвращенным из wait()/waitpid(), если дочерний элемент остановлен, а также вышел или был уничтожен. Таким образом, у вашего родителя есть возможность отправить ему SIGCONT, чтобы продолжить его, убить его, назначить его задачи другому ребенку, что угодно.

person Jemenake    schedule 18.01.2016
comment
Легендарное объяснение! - person benjamin; 03.06.2020
comment
так что по умолчанию wait() или waitpid() не информируют родительский процесс об остановке дочернего процесса сигналом? Поскольку в документации говорится, что выполнение вызывающего потока приостанавливается до тех пор, пока не завершится один из его дочерних элементов. . Поэтому мне не ясно, может ли завершение быть из-за сигнала - person brucebanner; 07.04.2021
comment
Ах, условия не очень ясны... моя вина. Завершено означает, что процесс завершился (или завершился сбоем из-за сбоя, или был уничтожен сигналом SIGKILL), и родительскому процессу доступен код выхода для проверки. Там, где я использовал «остановлено» выше, я действительно должен был сказать «приостановлено» или «приостановлено» (но сигналом для этого является SIGSTOP, поэтому я небрежно сказал «остановлено»). Приостановленные процессы (например, когда вы используете Ctrl-z в оболочке) можно возобновить позже. Итак, в любое время, когда процесс завершается (через exit(val), SIGKILL, segfault), должен разрешиться вызов wait(). - person Jemenake; 08.04.2021