Стиль строк 536–537 типичен; они ожидают завершения нужного порожденного процесса. Возвращаемое значение wait() является PID этого потомка. Оно сравнивается с PID порожденного процесса, status проверяется лишь на предмет равенства нулю (строка 538), в случае ненулевого результата потомок завершился неудачно. (Тест, хотя и правильный, грубый, но простой. Более правильным был бы тест наподобие 'if (WIFEXITED(status) && WEXITSTATUS(status) != 0)'.)
Из описаний и кода, представленных до сих пор, может показаться, что родительские программы должны выбрать определенный момент, чтобы ожидать завершения любого порожденного процесса, возможно, с опросом в цикле (как делает install.c), ожидая всех потомков. В разделе 10.8.3 «Родительский надзор: три различные стратегии» мы увидим, что это необязательно. Скорее, сигналы предоставляют ряд механизмов для использования уведомлениями родителей о завершении порожденных процессов.
9.1.6.2. Использование функций BSD: wait3() и wait4()
Системные вызовы BSD wait3() и wait4() полезны, если вы интересуетесь ресурсами, использованными порожденным процессом. Функции нестандартны (что означает, что они не являются частью POSIX), но широко доступны, в том числе на GNU/Linux. Объявления следующие:
#include
#include
/* Под GNU/Linux не нужно, но улучшает переносимость */
#include
#include
pid_t wait3(int *status, int options, struct rusage *rusage);
pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
Переменная status та же, что и для wait() и waitpid(). Все описанные ранее макросы (WIFEXITED() и т.д.) могут использоваться и с ними.
Значение options также то же самое, что и для waitpid(): либо 0, либо побитовое ИЛИ с одним или обоими флагами WNOHANG и WUNTRACED.
wait3() ведет себя подобно wait(), получая сведения о первом доступном порожденном зомби, a wait4() подобна waitpid(), получая сведения об определенном процессе. Обе функции возвращают PID потомка, -1 при ошибке или 0, если нет доступных процессов и был использован флаг WNOHANG. Аргумент pid может принимать те же значения, что и аргумент pid для waitpid().
Ключевым отличием является указатель struct rusage. Если он не равен NULL, система заполняет ее сведениями о процессе. Эта структура описана в POSIX и в справочной странице
struct rusage {
struct timeval ru_utime; /* используемое время пользователя */
struct timeval ru_stime; /* используемое системное время */
long ru_maxrss; /* максимальный размер резидентного набора */
long ru_ixrss; /* общий размер разделяемой памяти */
long ru_idrss; /* общий размер не разделяемых данных */
long ru_isrss; /* общий размер не разделяемого стека */
long ru_minflt; /* использование страниц */
long ru_majflt; /* ошибок страниц */
long ru_nswap; /* подкачек */
long ru_inblock; /* блочных операций ввода */
long ru_oublock; /* блочных операций вывода */
long ru_msgsnd; /* посланных сообщений */
long ru_msgrcv; /* полученных сообщений */
long ru_nsignals; /* полученных сигналов */
long ru_nvcsw; /* добровольных переключений контекста */
long ru_nivcsw; /* принудительных переключений контекста */
};
Чисто BSD системы (4.3 Reno и более поздние) поддерживают все поля. В табл. 9.2 описаны доступность различных полей struct rusage для POSIX и Linux.
Таблица 9.2. Доступность полей struct rusage
| Поле | POSIX | Linux | Поле | POSIX | Linux |
|---|---|---|---|---|---|
ru_utime | √ | ≥ 2.4 | ru_nswap | ≥2.4 | |
ru_stime | √ | ≥2.4 | ru_nvcsw | ≥2.6 | |
ru_minflt | ≥2.4 | ru_nivcsw | ≥2.6 | ||
ru_majflt | ≥2.4 |