Стандартом определены лишь поля, помеченные «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()
».
9.2. Группы процессов
Мы уже видели, что waitpid()
позволяет вам ждать любой процесс в данной группе процессов. В разделе 10.6.7 «Отправка сигналов: kill()
и killpg()
» мы увидим также, что вы можете отправить сигнал всем процессам в определенной группе процессов. (Всегда применяется проверка прав доступа; вы не можете послать сигнал процессу, которым не владеете.)
9.2.1. Обзор управления заданиями
Управление заданиями является сложной темой, той, в которую мы решили не погружаться в данной книге. Однако, здесь приведен краткий концептуальной обзор.
Устройство терминала (физическое или другое) с работающим на нем пользователем называется
pdksh
, zsh
или ksh93
[93], которая может осуществлять управление заданиями. Мы называем такую оболочку
Каждое задание, запущенное управляющей заданиями оболочкой, будь то простая программа или конвейер, получает отдельный идентификатор группы процессов. Таким способом оболочка может манипулировать заданием как отдельной сущностью, хотя в нем может быть несколько процессов.
Управляющий терминал также имеет связанный с ним идентификатор группы процессов. Когда пользователь набирает специальный символ, такой, как CTRL-C для «прерывания» или CTRL-Z для «остановки», ядро посылает данный сигнал процессам в группе процессов терминала.