9.1.6.2. Использование функций BSD: wait3() и wait4()

9.1.6.2. Использование функций BSD: wait3() и wait4()

Системные вызовы BSD wait3() и wait4() полезны, если вы интересуетесь ресурсами, использованными порожденным процессом. Функции нестандартны (что означает, что они не являются частью POSIX), но широко доступны, в том числе на GNU/Linux. Объявления следующие:

#include <sys/types.h> /* Обычный */

#include <sys/time.h>

 /* Под GNU/Linux не нужно, но улучшает переносимость */

#include <sys/resource.h>

#include <sys/wait.h>

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 и в справочной странице getrusage(2):

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

Стандартом определены лишь поля, помеченные «POSIX». Хотя Linux определяет полную структуру, ядро 2.4 поддерживает лишь поля времени пользователя и системного времени. Ядро 2.6 поддерживает также поля, связанные с переключением контекста.[92]

Наиболее интересными полями являются ru_utime и ru_stime, использование времени процессора в режиме пользователя и ядра соответственно. (Время процессора в режиме пользователя является временем, потраченным на исполнение кода уровня пользователя. Время процессора в режиме ядра является временем, потраченным в ядре в пользу процесса.)

Эти два поля используют struct timeval, которая содержит значения времени с точностью до микросекунд. Дополнительные сведения по этой структуре см. в разделе 14.3.1 «Время в микросекундах: gettimeofday()».

В BSD 4.2 и 4.3 аргумент status функций wait() и wait3() был union wait. Он умещался в int и предоставлял доступ к тем же сведениям, которые выдают современные макросы WIFEXITED() и др., но через членов объединения. Не все члены были действительными во всех случаях. Эти члены и их использование описаны в табл. 9.3.

Таблица 9.3. union wait 4.2 и 4.3 BSD

Макрос POSIX Член объединения Использование Значение WIFEXITED() w_termsig w.w_termsig == 0 True при нормальном завершении WEXITSTATUS() w_retcode code = w.w_retcode Статус завершения, если не по сигналу WIFSIGNALED() w_termsig w.w_temsig != 0 True, если завершен по сигналу WTERMSIG() w_termsig sig = w.w_termsig Сигнал, вызвавший завершение WIFSTOPPED() w_stopval w.w_stopval == WSTOPPED True, если остановлен WSTOPSIG() w_stopsig sig = w.w_stopsig Сигнал, вызвавший остановку WCOREDUMP() w_coredump w.w_coredump != 0 True, если потомок сделал снимок образа

POSIX не стандартизует union wait, a BSD 4.4 не документирует его, используя вместо этого макросы POSIX. GLIBC делает несколько бросков, чтобы заставить использующий его старый код продолжать работать. Мы опишем его здесь главным образом для того, чтобы вы увидев его — узнали; новый код должен использовать макросы, описанные в разделе 9.1.6.1 «Использование функций POSIX: wait() и waitpid()».