Жизненный цикл процесса в Unix

Для создания нового процесса существующий процесс, как правило, клонирует сам себя с помощью системного вызова fork. В результате формируется копия исходного процесса, имеющая лишь некоторые отличия. В частности, новому процессу присваивается собственный идентификатор, и учет ресурсов ведется для него независимо от предка.

Системный вызов fork имеет уникальное свойство: он возвращает два разных значения. В дочернем процессе это будет 0, а в родительском — идентификатор процесса-потомка. Поскольку в остальном процессы идентичны, они должны проверять результат вызова, чтобы определить, какую роль следует играть в дальнейшем.

После завершения системного вызова fork дочерний процесс обычно запускает новую программу с помощью одного из системных вызовов семейства ехес4. Все вызовы этого семейства выполняют приблизительно одинаковые действия: они замещают сегмент кода процесса и устанавливают сегменты памяти в исходное состояние. Формы вызовов ехес различаются только способами указания аргументов командной строки и переменных среды, передаваемых новой программе. Когда система загружается, ядро самостоятельно запускает несколько процессов. Наиболее важный из них — это демон init, идентификатор которого всегда равен 1. Демон init отвечает за выполнение сценариев запуска системы, хотя характер его действий неодинаков в UNIX и Linux. Все процессы, кроме тех, что создаются ядром, являются потомками демона init.

Демон init играет и другую важную роль в управлении процессами. Завершающийся процесс вызывает функцию _exit, чтобы уведомить ядро о своей готовности прекратить работу. В качестве параметра функции _exit передается код завершения — целое число, обозначающее причину останова процесса. Нулевой код свидетельствует об успешном завершении процесса.

Ядро системы требует, чтобы, прежде чем процесс окончательно исчезнет, его удаление было подтверждено родительским процессом с помощью системного вызова wait. Этот вызов возвращает код завершения потомка (или сообщает о причине его уничтожения, если завершение не было естественным) и, в случае необходимости, статистику использования ресурсов.

Описанный механизм работает нормально, если родительский процесс завершается позже порожденных им процессов и выполняет системные вызовы wait для их уничтожения. Если же родительский процесс завершается раньше срока, то ядро "понимает", что вызова wait не последует, и переназначает все "осиротевшие" процессы демону init. Он берет их под свой контроль, осуществляя для каждого из них вызов wait.

 

Комментарии (0)

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.