Создание процессов и исполнение программ



Скачать 336,76 Kb.
страница6/7
Дата12.09.2017
Размер336,76 Kb.
1   2   3   4   5   6   7

Ожидание порожденного процесса


После завершения по exit(2) или по сигналу, процесс переходит в состояние, известное как «зомби». В этом состоянии процесс не исполняется, не имеет пользовательской области, адресного пространства и открытых файлов и не использует большинство других системных ресурсов. Однако «зомби» занимает запись в таблице процессов и сохраняет идентификатор процесса и идентификатор родительского процесса. Эта запись используется для хранения слова состояния процесса, в котором хранится код завершения процесса (параметр exit(2)), если процесс завершился по exit(2) или номер сигнала, если процесс завершился по сигналу.

На самом деле, главным назначением «зомби» является защита идентификатора процесса (pid) от переиспользования. Дело в том, что родительские процессы идентифицируют своих потомков на основе их pid, а ядро может использовать свободные pid для вновь создаваемых процессов. Поэтому, если бы не существовало записей-«зомби», была бы возможна ситуация, когда потомок с pid=21285 завершается, а родитель, не получив код возврата этого потомка, создает новый подпроцесс и система выделяет ему тот же pid. После этого родитель уже не сможет объяснить системе, какой из потомков с pid-21285 его интересует, и не сможет понять, к какому из потомков относится полученное слово состояния.

Также, если «зомби» является последним из группы процессов или сессии, то соответствующая группа процессов или сессия продолжают существовать, пока существует зомби.

В выводе команды ps(1), процессы-зомби отмечаются надписью в колонке, где для нормальных процессов выводится имя программы. Также, в форматах вывода, в которых показывается статус исполнения процесса, процессы-зомби имеют статус Z.

Название «зомби» связано с тем, что обычные процессы можно «убить» сигналом, но процессы-зомби на сигналы не реагируют, то есть «убить» их невозможно. Для уничтожения «зомби», родитель такого процесса должен считать его слово состояния системным вызовом wait(2), waitpid(2) или waitid(2). Эти системные вызовы рассматриваются далее. В системах семейства Unix код завершения процесса может быть считан только родителем этого процесса.

Идентификаторы процессов и записи в таблице процессов представляют собой ценные системные ресурсы, поэтому хорошим тоном считается как можно быстрее освобождать ненужные записи. Если ваша программа создает подпроцессы, она должна позаботиться о своевременном сборе их кодов завершения.

Если родительский процесс завершается, все его потомки, как продолжающие исполнение, так и «зомби», усыновляются процессом с pid=1. При нормальной работе системы этот процесс исполняет программу /bin/init, которая большую часть времени проводит в системном вызове wait(2), отслеживая состояние запущенных ею системных процессов. Поэтому коды завершения усыновленных «зомби» быстро считываются и соответствующие записи в таблице процессов освобождаются.

      1. Ожидание порожденного процесса - wait(2)


Процесс может синхронизоваться с завершением порожденного процесса с помощью системного вызова wait(2). Если вызывается wait(2), а у процесса нет ни одного незавершенного подпроцесса, wait(2) немедленно возвращает -1 и устанавливает errno равной ECHILD. Иначе вызывающий процесс:

1. засыпает, если существует незавершившийся подпроцесс.

2. возвращает управление немедленно, если существует подпроцесс, который уже завершился, но к нему не применялся wait(2).

В обоих вышеперечисленных случаях, wait(2) возвращает идентификатор завершившегося подпроцесса. Кроме того, слово состояния подпроцесса сохраняется в параметре wait(2).

3. возвращает значение -1 и устанавливает errno в EINTR, если wait(2) был прерван сигналом. Если это произошло, а вы по-прежнему хотите дождаться завершения подпроцесса, вы должны еще раз вызвать wait(2).

Параметр wait(2) - указатель на целое число, по которому размещается слово состояния подпроцесса. Если вас не интересует слово состояния подпроцесса, вы можете использовать нулевой указатель.

Подпроцесс может завершиться штатно (вызовом exit(2)), или он может быть убит необработанным сигналом. Эти два варианта можно различить анализом содержимого младших 16 бит слова состояния, которое формирует wait(2). Младший байт слова состояния содержит номер сигнала или ноль, если процесс был завершен по exit(2). Вспомним, что нумерация сигналов начинается с 1, то есть сигнала с номером ноль не существует. Второй по старшинству байт содержит параметр exit(2) или 0, если процесс завершился по сигналу. Содержимое старших двух байтов целочисленного значения не определено, на практике оно обычно 0. В заголовочном файле определено несколько макросов, используемых для анализа содержимого слова состояния. Эти макросы описаны на странице руководства wstat(2) и будут обсуждаться далее.

Если процесс ожидает завершения нескольких подпроцессов, то порядок, в котором они завершатся, неизвестен, а порядок получения слов состояния может не соответствовать порядку их завершения. Поэтому ваша программа не должна зависеть от предполагаемого порядка завершения подпроцессов.


      1. Слово состояния wait(2)


Когда процесс ожидает получения слова состояния своих подпроцессов с использованием wait(2) или waitpid(3C), то это слово может быть проанализировано при помощи макросов, определенных в . Эти макросы обсуждаются на странице руководства wstat(5).

WIFEXITED(stat) Ненулевое значение, если это слово состояния получено от подпроцесса, завершившегося по exit(2).

WEXITSTATUS(stat) Если значение WIFEXITED(stat) ненулевое, этот макрос возвращает код завершения, переданный подпроцессом вызову exit(2), или возвращенный его функцией main(), иначе код возврата не определен.

WIFSIGNALED(stat) Возвращает ненулевое значение, если это слово состояния получено от подпроцесса, который был принудительно завершен сигналом.

WTERMSIG(stat) Если значение WIFSIGNALED(stat) ненулевое, этот макрос возвращает номер сигнала, который вызвал завершение подпроцесса, иначе код возврата не определен.

WIFSTOPPED(stat) Возвращает ненулевое значение, если слово состояния получено от приостановленного подпроцесса (wait(2) не реагирует на приостановленные подпроцессы, такое слово состояния может быть получено только вызовом waitpid(2)).

WSTOPSIG(stat) Если значение WIFSTOPPED(stat) ненулевое, этот макрос возвращает номер сигнала, который вызвал приостановку подпроцесса, иначе код возврата не определен.

WIFCONTINUED(stat) Возвращает ненулевое значение, если слово состояния получено от процесса, продолжившего исполнение (wait(2) не реагирует на приостановленные подпроцессы, такое слово состояния может быть получено только вызовом waitpid(2)).

WCOREDUMP(stat) Если значение WIFSIGNALED(stat) ненулевое, этот макрос возвратит ненулевое значение, если был создан посмертный дамп памяти (core-файл) завершившегося подпроцесса. Факт создания дампа памяти определяется по номеру сигнала; завершение по некоторым сигналам, таким, как SIGSEGV и SIGFPE, всегда приводит к созданию дампа памяти, завершение по остальным сигналам никогда не создает такой дамп.




      1. Поделитесь с Вашими друзьями:
1   2   3   4   5   6   7


База данных защищена авторским правом ©grazit.ru 2017
обратиться к администрации

    Главная страница