Linux программирование в примерах
Обратите внимание, что этот макрос не стандартный. Системы GNU/Linux, Solaris и BSD его поддерживают, однако некоторые другие системы Unix нет. Поэтому и здесь, если нужно его использовать, заключите код внутрь '
'.#ifdef WCOREDUMP ... #endifБольшинство программ не интересуются, почему завершился порожденный процесс; им просто нужно, что он завершился, возможно, отметив, было завершение успешным или нет. Программа GNU Coreutils
демонстрирует такое простое использованиеinstall,fork()иexeclp(). Опцияwait()заставляет-sзапустить для устанавливаемого двоичного исполняемого файла программуinstall.stripудаляет из исполняемого файла отладочную и прочую информацию. Это может сохранить значительное пространство. На современных системах с многогигабайтными жесткими дисками при установке редко бывает необходимо использовать(stripдля исполняемых файлов.) Вот функцияstripизstrip():install.с513 /* Вырезать таблицу имен из файла PATH.514 Мы могли бы сначала вытащить из файла магическое число515 для определения, нужно ли вырезать, но заголовочные файлы и516 магические числа варьируют от системы к системе так сильно, что517 сделать его переносимым было бы очень трудно. Не стоит усилий. */518519 static void520 strip (const char *path)521 {522 int status;523 pid_t pid = fork();524525 switch (pid)526 {527 case -1:528 error(EXIT_FAILURE, errno, _("fork system call failed"));529 break;530 case 0: /* Порожденный. */531 execlp("strip", "strip", path, NULL);532 error(EXIT_FAILURE, errno, _("cannot run strip"));533 break;534 default: /* Родитель. */535 /* Родительский процесс. */536 while (pid != wait(&status)) /* Ждать завершения потомка. */537 /* Ничего не делать. */ ;538 if (status)539 error(EXIT_FAILURE, 0, _("strip failed"));540 break;541 }542 }Строка 523 вызывает
. Затем операторfork()предпринимает нужное действие для возвращения ошибки (строки 527–529), порожденного процесса (строки 530–533) и родительского процесса (строки 534–539).switchСтиль строк 536–537 типичен; они ожидают завершения нужного порожденного процесса. Возвращаемое значение wa
является PID этого потомка. Оно сравнивается с PID порожденного процесса,it()проверяется лишь на предмет равенства нулю (строка 538), в случае ненулевого результата потомок завершился неудачно. (Тест, хотя и правильный, грубый, но простой. Более правильным был бы тест наподобие 'status'.)if (WIFEXITED(status) && WEXITSTATUS(status) != 0)Из описаний и кода, представленных до сих пор, может показаться, что родительские программы должны выбрать определенный момент, чтобы ожидать завершения любого порожденного процесса, возможно, с опросом в цикле (как делает
), ожидая всех потомков. В разделе 10.8.3 «Родительский надзор: три различные стратегии» мы увидим, что это необязательно. Скорее, сигналы предоставляют ряд механизмов для использования уведомлениями родителей о завершении порожденных процессов.install.c9.1.6.2. Использование функций BSD:
иwait3()wait4()Системные вызовы BSD
иwait3()полезны, если вы интересуетесь ресурсами, использованными порожденным процессом. Функции нестандартны (что означает, что они не являются частью POSIX), но широко доступны, в том числе на GNU/Linux. Объявления следующие:wait4()#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: либо 0, либо побитовое ИЛИ с одним или обоими флагамиwaitpid()иWNOHANG.WUNTRACEDведет себя подобноwait3(), получая сведения о первом доступном порожденном зомби, await()подобнаwait4(), получая сведения об определенном процессе. Обе функции возвращают PID потомка, -1 при ошибке или 0, если нет доступных процессов и был использован флагwaitpid(). АргументWNOHANGможет принимать те же значения, что и аргументpidдляpid.waitpid()Ключевым отличием является указатель
. Если он не равенstruct rusage, система заполняет ее сведениями о процессе. Эта структура описана в POSIX и в справочной странице getrusage(2):NULL