$ echo $$ Выводим идентификатор процесса командной оболочки

400

$ find / 2> /dev/null | wc — l & Результатом будут два процесса в фоновой группе

[1] 659

$ sort < longlist | uniq — c Результатом будут два процесса в активной группе

На этом этапе, помимо командной оболочки (bash), запущены программы find, wc, sort и uniq.

34.2. Группы процессов

Каждый процесс имеет числовой идентификатор PGID, который определяет его принадлежность к той или иной группе. Новый процесс наследует PGID своего родителя. Для получения текущего идентификатора группы используется вызов getpgrp().

#include

pid_t getpgrp(void);

Всегда успешно возвращает идентификатор группы вызывающего процесса

Значение, возвращенное getpgrp(), совпадает с идентификатором вызывающего процесса, этот процесс является лидером своей группы.

Рис. 34.1.Отношения между группой процессов, сессиями и контролирующим терминалом

Системный вызов setpgid() позволяет сменить группу процесса с идентификатором pid на значение, указанное в аргументе pgid.

#include

int setpgid(pid_t pid, pid_t pgid);

Возвращает 0 при успешном завершении или –1, если случилась ошибка

Если в качестве pid указать 0, изменится идентификатор PGID вызывающего процесса. Если присвоить 0 аргументу pgid, PGID процесса, указанного с помощью pid, станет таким же, как идентификатор этого процесса. Таким образом, следующие вызовы setpgid() являются эквивалентными.

setpgid(0, 0);

setpgid(getpid(), 0);

setpgid(getpid(), getpid());

Если аргументы pid и pgid указывают на один и тот же процесс (то есть если pgid равен 0 или идентификатору процесса, заданному с помощью pid), создается новая группа процессов и ее лидером становится заданный процесс (то есть PGID и идентификатор процесса совпадают). Если в этих аргументах указаны разные значения (то есть когда pgid не равен 0 и не совпадает с идентификатором процесса, заданного с помощью pid), вызов setpgid() используется для перемещения процессов между группами. Обычно вызовы setpgid() и setsid() (описан в разделе 34.3), выполняют такие программы, как командная оболочка или login(1). В разделе 37.2 вы увидите, что вызов setsid() используется на одном из этапов превращения процесса в процесс-демон.

Вызов setpgid() имеет несколько ограничений.

• Аргумент pid может указывать только на вызывающий процесс или его потомка. Нарушение этого правила приводит к ошибке ESRCH.

• При перемещении процесса между группами вызывающий процесс, процесс, указанный с помощью pid (которые могут совпадать), и текущая группа должны принадлежать к одной и той же сессии. Нарушение этого правила приводит к ошибке EPERM.

• Процесс, на который указывает аргумент pid, не должен быть лидером сессии. Нарушение этого правила приводит к ошибке EPERM.

• Процесс не должен менять идентификатор PGID своего потомка, если тот уже вызвал exec(). Нарушение этого правила приводит к ошибке EACCES. Данное ограничение связано с тем, что программа может быть введена в заблуждение, если изменить идентификатор группы процессов уже после ее запуска.

Использование setpgid() для управления заданиями в командной оболочке

Тот факт, что процессу запрещено менять идентификатор PGID своего потомка, если тот успел выполнить вызов exec(), влияет на архитектуру командных оболочек, управляющих заданиями, которые, в свою очередь, имеют следующие требования.

• Все процессы в задании (то есть в команде или конвейере) должны быть помещены в одну и ту же группу (желаемый результат можно увидеть на примере двух групп процессов, созданных оболочкой bash на рис. 34.1). На этом этапе командная оболочка может использовать вызов killpg() (или, как вариант, kill() с отрицательным аргументом pid) для одновременной отправки всем членам группы сигналов, управляющих заданием. Естественно, этот этап необходимо выполнить до отправки сигналов подобного рода.

• Все дочерние процессы должны быть доставлены в группу до запуска программы, поскольку сама программа ничего не знает о манипуляциях с идентификатором группы процессов.

Перейти на страницу:

Похожие книги