Группа процессов является совокупностью связанных процессов, таких, как конвейер оболочки, каждому из которых присвоен один и тот же идентификатор группы процессов. Идентификатор группы процессов равен PID начального участника группы процессов; таким образом, идентификаторы группы процессов разделяют пространство имен идентификаторов процессов. Когда создается новая группа процессов, ядро выделяет структуру группы процессов, которая будет с ней связана. Эта структура группы процессов записывается в хеш-таблицу таким образом, чтобы ее можно было быстро найти.
Процесс всегда является членом одной группы процессов. При своем создании каждый процесс помещается в группу своего родительского процесса. Новые группы процессов создают такие программы, как оболочки, обычно помещая в группу связанные порожденные процессы. Процесс может изменить свою группу процессов или группу порожденного процесса, создав новую группу процессов или переместив процесс в существующую группу с использованием системного вызова setpgid. Например, когда оболочка хочет установить новый конвейер, ей необходимо поместить процессы в конвейере в группу процессов, отличающуюся от ее собственной, таким образом, чтобы конвейер можно было контролировать независимо от оболочки. Оболочка начинает с создания первого процесса в конвейере, который вначале имеет тот же самый идентификатор группы процессов, как у оболочки. До выполнения программы назначения первый процесс вызывает setpgid, чтобы установить в качестве идентификатора своей группы процессов свой собственный PID. Этот системный вызов создает новую группу процессов с порожденным процессом в качестве лидера группы процессов. Когда оболочка запускает для конвейера дополнительные процессы, каждый порожденный процесс использует setpgid, чтобы присоединиться к существующей группе процессов.
В нашем примере оболочки, создающей новый конвейер, имеется состояние гонки (race condition). По мере запуска оболочкой в конвейере дополнительных процессов каждый помещается в группу процессов, созданную первым процессом в конвейере. Эти соглашения проводятся в жизнь системным вызовом setpgid. Он ограничивает набор идентификаторов группы процессов, которые могут быть установлены для процесса, либо равным собственному PID процесса, либо значением идентификатора другой группы процессов в его сеансе. К сожалению, если процесс конвейера, не являющийся лидером группы процессов, создан до того, как лидер группы процессов завершил свой вызов setpgid, вызов setpgid для присоединения к группе процессов завершится неудачей. Поскольку вызов setpgid разрешает родителям устанавливать группу процессов своих потомков (в пределах ограничений, налагаемых интересами безопасности), оболочка может избежать этого состязания, заставив вызов setpgid изменить группу процессов потомка как во вновь порожденном процессе, так и в родительской оболочке. Этот алгоритм гарантирует, что вне зависимости от того, какой процесс запустится первым, будет существовать группа процесса с нужным лидером группы процессов. Оболочка может также избежать состязания, используя вариант vfork системного вызова fork, который заставляет процесс родителя ожидать до тех пор, пока порожденный процесс либо не выполнит системный вызов exec, либо не завершится. Кроме того, если первоначальные члены группы процессов завершатся до того, как все члены конвейера присоединятся к группе (например, если лидер группы процессов завершится до того, как к группе присоединится второй процесс), вызов setpgid может завершиться неудачей. Оболочка может избежать этого состязания, обеспечив помещение в группу процессов всех порожденных процессов без использования системного вызова wait, обычно путем блокирования сигнала SIGCHLD таким образом, что оболочка не будет еще уведомлена, если потомок завершится. Пока существуют члены группы процессов, даже в виде процессов зомби, к группе процессов могут присоединяться дополнительные процессы.
Имеются дополнительные ограничения на системный вызов setpgid. Процесс может присоединиться к группе процессов лишь в рамках своего текущего сеанса (который обсуждается в следующем разделе), и он не должен до этого делать системный вызов exec. Последнее ограничение предназначено для избежания неожиданного поведения, если процесс будет перемещен в другую группу процессов после начала его выполнения. Поэтому, когда оболочка вызывает setpgid как в родительском, так и в порожденном процессе после fork, вызов, сделанный родителем, завершится неудачей, если порожденный процесс уже выполнил вызов exec. Однако потомок будет уже успешно присоединен к группе процессов, и эта неудача безопасна.
- 22/10/2010 20:29 - Ограничения тюрьмы
- 22/10/2010 16:02 - Реализация тюрьмы
- 22/10/2010 11:30 - Семантика тюрьмы
- 19/10/2010 04:06 - Тюрьмы
- 17/10/2010 19:25 - Управление заданиями
- 12/10/2010 02:42 - Доставка сигнала
- 11/10/2010 07:30 - Отправка сигнала
- 10/10/2010 22:11 - История сигналов
- 10/10/2010 01:09 - Процедуры вычисления приоритета потока
- 09/10/2010 12:36 - Сигналы