Linux программирование в примерах
Между механизмами, которые ожидают завершения потомков, и сигнальными механизмами, которые мы еще не обсуждали, есть значительное взаимодействие. Что из них описать вначале представляет собой нечто вроде проблемы курицы и яйца; мы решили сначала поговорить сначала о механизмах ожидания порожденного процесса, а глава 10 «Сигналы» дает полный рассказ о сигналах.
Пока достаточно понять, что сигнал является способом уведомления процесса о том, что произошло некоторое событие. Процессы могут генерировать сигналы, которые посылаются самим себе, или сигналы могут посылаться извне другими процессами или пользователем за терминалом. Например, CTRL-C посылает сигнал «прерывания», a CTRL-Z посылает сигнал управления работой «стоп».
По умолчанию, многие сигналы, такие, как сигнал прерывания, заставляют получающий процесс закончиться. Другие, такие, как сигналы управления работами, вызывают изменение его состояния. Механизмы ожидания порожденного процесса могут определить, претерпел ли процесс сигнал завершения, и если да, какой это был сигнал. То же верно и для остановки процесса и, на некоторых системах возобновления процесса.
9.1.6.1. Использование функций POSIX:
иwait()waitpid()Первоначальным системным вызовом V7 был
. Более новым вызовом POSIX, основанным на возможностях BSD, являетсяwait(). Объявления функций следующие:waitpid()#include <sys/types.h> /* POSIX */#include <sys/wait.h>pid_t wait(int *status);pid_t waitpid(pid_t pid, int *status, int options);ждет завершения любого порожденного процесса; сведения о том, как он завершился, возвращаются вwait(). (Вскоре мы обсудим, как интерпретировать*status.) Возвращаемое значение является PID завершившегося процесса или -1, если возникла ошибка.*statusЕсли порожденных процессов нет,
возвращает -1 сwait(), установленным вerrno(отсутствует порожденный процесс). В противном случае, функция ждет завершения первого порожденного процесса или поступления сигнала.ECHILDФункция
дает возможность ждать завершения определенного порожденного процесса. Она предоставляет значительную гибкость и является предпочтительной для использования функцией. Она также возвращает PID закончившегося процесса или -1 при возникновении ошибки. Аргументы следующие:waitpid()pid_t pidЗначение указывает, завершения какого порожденного процесса ждать как по-настоящему
, так и по группе процесса. Смысл значенияpidследующий:pidЖдать завершения любого порожденного процесса с ID группы процесса, равной абсолютному значениюpid < -1.pidЖдать завершения любого порожденного процесса. Таким способом работаетpid = -1.wait()Ждать завершения любого порожденного процесса с ID группы процесса, равной ID группе родительского процесса.pid = 0Ждать завершения конкретного процесса с PID, равнымpid > 0.pidint *statusТо же, что и для
.wait()определяет различные макросы, которые интерпретируют значение в<sys/wait.h>, которые мы вскоре опишем*statusint optionsЭтот параметр должен быть равен либо 0, либо побитовым ИЛИ одного или более из следующих флагов:
WNOHANGЕсли ни один порожденный процесс не завершился, вернуться немедленно. Таким способом можно периодически проверять, не закончился ли какой- нибудь порожденный процесс. (Такая периодическая проверка известна как опрашивание события.)
WUNTRACEDВернуть сведения о порожденном процессе, который остановился, но еще не завершился. (Например, для управления работой.)
WCONTINUED(XSI.) Вернуть сведения о порожденном процессе, который продолжился, если его статус не сообщался с момента изменения. Это также для управления работой. Этот флаг является расширением XSI и не доступен под GNU/Linux.
С заполненным значением
работают несколько макросов, определяющие, что случилось. Они имеют тенденцию образовывать пары: один макрос для определения, что что-то случилось, и если этот макрос истинен, еще один макрос позволяет получить подробности. Макросы следующие:*statusWIFEXITED(status)Этот макрос не равен нулю (true), если процесс завершился (в противоположность изменению состояния).
WEXITSTATUS(status)Этот макрос дает статус завершения; он равен восьми наименее значимым битам значения, переданного
или возвращенного изexit(). Этот макрос следует использовать лишь еслиmain()равен true.WIFEXIDED(status)WIFSIGNALED(status)Этот макрос не равен нулю, если процесс подвергся действию завершающего сигнала death-by-signal.
WTERMSIG(status)Этот макрос предоставляет номер сигнала, который завершил процесс. Этот макрос следует использовать, лишь когда
равен true.WIFSIGNALED(status)WIFSTOPPED(status)Этот макрос не равен нулю, если процесс был остановлен.
WSTOPSIG(status)Этот макрос предоставляет номер сигнала, который остановил процесс. (Процесс остановить могут несколько сигналов.) Этот макрос следует использовать лишь когда
равен true. Сигналы управления работами обсуждаются в разделе 10.8.2 «Сигналы управления работой».WIFSTOPPED(status)WIFCONTINUED(status)(XSI.) Этот макрос не равен нулю, если процесс был продолжен. Соответствующего макроса
нет, поскольку лишь один сигнал может вызвать продолжение процесса.WCONTSIG()Обратите внимание, что этот макрос является расширением XSI и в частности, он недоступен в GNU/Linux. Следовательно, если вы хотите его использовать, заключите код внутри '
'.#ifdef WIFCONTINUED ... #endifWCOREDUMP(status)(Общий.) Этот макрос не равен нулю, если процесс создал снимок. Снимок процесса (core dump) является образом запущенного процесса в памяти, созданном при завершении процесса. Он предназначен для использования впоследствии при отладке. Системы Unix называют файл
, тогда как системы GNU/Linux используютcore, гдеcorе.<i>pid</i>является ID завершившегося процесса. Определенные сигналы завершают процесс и автоматически создают снимок процесса.<i>pid</i>