Олег Цилюрик - QNX/UNIX: Анатомия параллелизма стр 9.

Шрифт
Фон

Функции семейства exec(), напротив, подменяют исполняемый код текущего процесса (не изменяя его идентификатор PID, права доступа, внешние ресурсы процесса, а также находящийся в том же адресном пространстве) исполняемым кодом из другого файла. Поэтому используются эти вызовы непосредственно после fork() для замены копии вызывающего процесса новым (это классическая UNIX-технология использования).

Функции семейства spawn(), напротив, порождают новый процесс (с новым идентификатором PID и в новом адресном пространстве). Все формы вызовов spawn() после подготовительной работы (иногда очень значительной) в конечном итоге ретранслируются в вызов базовой формы spawn(), который последним действием своего выполнения и посылает сообщение procnto (менеджер процессов QNX, "территориально" объединенный с микроядром системы в одном файле).

Базовый вызов spawn() определяется следующим образом:

#include <spawn.h>

pid_t spawn(const char* path, int fd_count, const int fd_map[],

const struct inheritance* inherit, char* const argv[],

char* const envp[]);

где path - полное имя исполняемого бинарного файла;

fd_count - размерность следующего за ним массива fd_map;

fd_map - массив файловых дескрипторов, которые вы хотели бы унаследовать в дочернем процессе от родительского. Если fd_count не равен 0 (то есть может иметь значения вплоть до константы OPEN_MAX), то fd_map должен содержать список из fd_count файловых дескрипторов. Если же fd_count равен 0, то дочерний процесс наследует все родительские дескрипторы, исключая те, которые созданы с флагом PD_CLOEXEC функции fcntl();

inherit - системная структура (см. системные определения) типа struct inheritance, содержащая как минимум:

unsigned long flags - один или более установленных бит:

SPAWN_CHECK_SCRIPT - позволить spawn() запускать требуемый командный интерпретатор, интерпретируя path как скрипт (интерпретатор указан в первой строке скрипта path);

SPAWN_SEARCH_PATH - использовать переменную окружения PATH для поиска выполняемого файла path;

SPAWN_SETGROUP - установить для дочернего процесса значение группы, специфицируемое членом (структуры) pgroup. Если этот флаг не установлен, дочерний процесс будет частью текущей группы родительского процесса;

SPAWN_SETND - запустить дочерний процесс на удаленном сетевом узле QNET, сам же удаленный узел специфицируется членом (структуры) nd (см. команду удаленного запуска on);

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

SPAWN_SETSIGMASK - использовать sigmask в качестве сигнальной маски дочернего процесса.

pid_t pgroup - группа дочернего процесса; имеет смысл, только если установлен флаг SPAWN_SETGROUP. Если флаг SPAWN_SETGROUP установлен и inherit.pgroup установлен как SPAWN_NEWPGROUP, то дочерний процесс открывает новую группу процессов с идентификатором группы (GID), равным PID этого нового процесса.

sigset_t sigmask - сигнальная маска дочернего процесса, если установлен флаг SPAWN_SETSIGMASK.

sigset_t sigdefault - набор сигналов дочернего процесса, для которых определяется реакция по умолчанию, если установлен флаг SPAWN_SETSIGDEF.

uint32_t nd - это совершенно уникальный (относительно других ОС, а значит, и всего POSIX) параметр QNX - дескриптор узла сети QNET, на котором должен быть запущен новый процесс. Это поле используется, только если установлен флаг SPAWN_SETND.

argv - указатель массива аргументов. Значение argv[0] должно быть строкой (char*), содержащей имя файла, загружаемого как процесс (но может быть NULL, если аргументы не передаются). Последний элемент массива argv обязан быть NULL. Само значение argv никогда не может быть NULL.

envp - указатель массива символьных строк переменных системного окружения (environment). Последний элемент массива envp обязан быть NULL. Каждый элемент массива является строкой (char*) вида: variable = value. Если само значение указателя envp равно NULL, то дочерний процесс полностью наследует копию окружения родителя. (Окружение процесса - всегда "копия", поэтому любые изменения, внесенные в окружение дочерним процессом, никак не отражаются на окружении его родителя.)

Примечание

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

Правила наследования (и ненаследования) параметров дочернего процесса от родителя (RID, RGID и других атрибутов) жестко регламентированы, достаточно сложны (в зависимости от флагов) и могут быть уточнены в технической документации QNX. Отметим, что безусловно наследуются такие параметры, как: а) приоритет и дисциплина диспетчеризации; б) рабочий и корневой каталоги файловой системы. Не наследуются: установки таймеров процесса tms_utime, tms_stime, tms_cutime и tms_cstime, значение взведенного сигнала SIGALRM (это значение сбрасывается в ноль), файловые блокировки, блокировки и отображения памяти (shared memory), установленные родителем.

При успешном завершении вызов функции возвращает PID порожденного процесса. При неудаче возвращается -1 и errno устанавливается:

E2BIG - количество байт, заданное в списке аргументов или переменных окружения и превышающее ARG_MAX;

EACCESS - нет права поиска в каталогах префикса имени файла, или для файла не установлены права на выполнение, или файловая система по указанному пути была смонтирована с флагом ST_NOEXEC;

EAGAIN - недостаточно системных ресурсов для порождения процесса;

ERADF - недопустим хотя бы один из файловых дескрипторов в массиве fd_map;

EFAULT - недопустима одна из буферных областей, указанных в вызове;

ELOOP - слишком глубокий уровень символических ссылок к файлу или глубина префиксов (каталогов) в полном пути к файлу;

EMFILE - недостаточно ресурсов для отображения файловых дескрипторов в дочерний процесс;

ENAMETOOLONG - длина полного пути превышает PATH_MAX или длина компонента имени файла и пути превышает NAME_MAX;

ENOENT - файл нулевой длины или несуществующий префиксный компонент в полном пути;

ENOEXEC - файл, указанный как программа, имеет ошибочный для исполняемого файла формат;

ENOMEM - в системе недостаточно свободной памяти для порождения процесса;

ENOSYS - файловая система, специфицированная полным путевым именем файла, не предназначена для выполнения spawn();

ENOTDIR - префиксные компоненты пути исполняемого файла не являются каталогами;

Даже из этого очень краткого обзора вызова spawn() становятся очевидными некоторые вещи:

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

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке

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