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_count = 0, fd_map игнорируется и дочерний процесс наследует открытые файловые дескрипторы родителя (исключая те, которые были модифицированы с помощью fcntl() и флагом FD_CLOEXEC).
fd_map
Массив файловых дескрипторов, которые должен унаследовать дочерний процесс. Если fd_count не равен 0, то fd_map должен содержать ровно указанное число элементов, но не более OPEN_MAX. Первые три записи при этом используются в качестве stdin, stdout и stderr.

Если fdmap[X] равен SPAWN_FDCLOSED, то данный файловый дескриптор будет закрыт в дочернем процессе.
inherit
Указатель на struct inheritance, определяющий перечень наследуемых сущностей.

Note: Если необходимо использовать spawnp() удаленно, следует установить поле nd структуры struct inheritance с помощью функции netmgr_strtond().

argv
Указатель на массив аргументов процесса. Значение argv[0] не может быть установлено в NULL и должно представлять имя файла загружаемой программы. Последний член массива должен быть всегда равен NULL. Сам указатель argv не может быть равен NULL.
envp
Указатель на массив строк, представляющих переменные окружения. Последний член массива должен быть всегда равен NULL. Формат каждой строки должен быть следующим: variable=value. Если envp равен NULL, то дочерний процесс унаследует переменные окружения родителя.

Библиотека:

libc

Описание:

Функция spawn() создает и исполняет новый дочерний процесс на основе файла path.


Note: Если новый процесс является shell-скриптом, то его первая строка должна начинаться с #! с последующим именем программы-интерпретатора (опционально могут быть также переданы его аргументы). Скрипт также должен иметь разрешения на исполнение.

Данная функция относится только к ЗОСРВ «Нейтрино» (основано на стандарте POSIX 1003.1d). Системная библиотека также включает ряд специализированных функций вида spawn*(). Их имена содержат ряд дополнительных суффиксов:

Суффикс: Влияние на принимаемые аргументы:
e Массив переменных окружения.
l Список аргументов программы с завершающим символом NULL.
p Относительный путь. Если путь не содержит символ /, программа будет искаться по адресам, перечисленным в переменной PATH. Данный суффикс также позволяет конструкцию #!; см. SPAWN_CHECK_SCRIPT далее.
v Векторный формат аргументов программы.

Перечисленные на рисунке функции в конечном счете вызывают spawn():

spawnall.png
Рисунок 1. Большинство функций spawn*() предпринимают ряд настроечных действий перед отправкой сообщения procnto-* функцией spawn()

Дочерний процесс наследует следующие атрибуты родителя:

Дочерний процесс при этом имеет ряд отличий от родителя:

Дочерний процесс также будет иметь следующие отличия от родителя, если установлен флаг SPAWN_EXEC:

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

Доступ к переменным окружения в дочернем процессе осуществляется через environ.

Если path относится к файловой системе с установленным флагом ST_NOSUID, то: EUID, EGID, сохраненные UID/GID для потомка не меняются. В противном случае, если бит сохранения UID установлен, EUID потомка устанавливается в UID владельца файла path. Аналогичная история с установкой бита сохранения GID и GID владельца файла path. RUID, RGID и дополнительные идентификаторы групп остаются соответствующими родителю. EUID и EGID потомка сохраняются как сохраненные UID/GID для использования в setuid().


Note: Отношения родитель-потомок не означают, что потомок будет завершен при смерти родителя.

Мапирование файловых дескрипторов

Допустимо использовать параметры fd_count и fd_map для определения перечня наследуемых файловых дескрипторов.

Номер результирующего дескриптора соответствует позиции в массиве fd_map. Например, в потомке необходимо унаследовать файловые дескрипторы со значениями 1, 3 и 5:

int fd_map = { 1, 3, 5 };

В этом случае таблица соответствия дескрипторов в потомке и родителе будет иметь вид:

Дескрипторы потомка: Соответствующие дескрипторы родителя:
0 1
1 3
2 5

Если родительские файловые дескрипторы 1, 3 и 5 являются единственными и указано fd_count = 0, будут продублированы все файловые дескрипторы и таблица соответствия примет вид:

Дескрипторы потомка: Соответствующие дескрипторы родителя:
1 1
3 3
5 5

при этом в потомке дескрипторы 0, 2, 4 и 6 будут закрыты.

Если используется явный массив fd_map, то для воспроизведения предыдущей таблицы можно использовать SPAWN_FDCLOSE:

int fd_map = { SPAWN_FDCLOSE, 1, SPAWN_FDCLOSE, 3, SPAWN_FDCLOSE, 5 };


Caution: Используйте SPAWN_FDCLOSE с осторожностью для файловых дескрипторов 0, 1 и2. Если потомо вызовет open(), функция назначит открытому файлу наименьший доступный файловый дескриптор. Это может переназначить стандартные файловые потоки stdin, stdout и stderr. В этом случае некоторые функции, например, printf() будут использовать только что открытый файл для ввода-вывода, что может оказаться неочевидным.

Гораздо предсказуемее назначать файловые дескрипторы 0, 1 и 2 реальным открытым ресурсам (хотя бы /dev/null).


Возвращаемое значение:

Идентификатор дочернего процесса. Если возникла ошибка функция возвращает -1, код ошибки записывается в errno.


Note: Если установлен флаг SPAWN_EXEC в поле flags структуры struct inheritance, spawn() не возвращает управление в отсутствии ошибок.

Коды ошибок:

E2BIG
Размер списка аргументов и переменных окружения в байтах превышает ARG_MAX.
EACCESS
Поиск в директории, содержащей исполняемый файл, запрещен; отсутствует бит разрешения исполнение файла; файловая система смонтирована с флагом ST_NOEXEC.
EAGAIN
Недостаточно ресурсов для создания дочернего процесса.
EBADF
Запись в fd_map указывает на некорректный файловый дескриптор или возникла ошибка при дублировании файловых дескрипторов родителя.
EFAULT
Один из переданных буферов не является корректным.
EINTR
Функция прервана сигналом.
EINVAL
Один из аргументов некорректен (например, argv[0] равен NULL).
ELOOP
Слишком большой уровень вложения символьных ссылок или префиксов.
EMFILE
Недостаточно ресурсов для загрузки образа программы или мапирования файловых дескрипторов.
ENAMETOOLONG
Длина поля path превышает PATH_MAX или один из компонентов пути превышает NAME_MAX.
ENOENT
Файл, соответствующий аргументу path, пуст или один из компонентов пути не существует.
ENOEXEC
Файл имеет права на исполнение, но сам исполняемым не является. Данная ошибка не генерируется, если установлен флаг SPAWN_CHECK_SCRIPT для поля flags структуры struct inheritance.
ENOMEM
Недостаточно памяти для создания дочернего процесса.
ENOSYS
Функция spawn() не реализована для данной файловой системы.
ENOTDIR
Один из компонентов пути не является директорией.
ETXTBSY
Текстовый файл, который должен быть использован, занят (например, он может быть открыт для записи).

Классификация:

ЗОСРВ «Нейтрино»

Безопасность использования
Точка остановки потока
Нет
Обработчик прерываний
Нет
Обработчик сигналов
Да
В потоке
Да

Тематические ссылки:

struct inheritance, struct sched_param, execl(), execle(), execlp(), execlpe(), execv(), execve(), execvp(), execvpe(), getenv(), netmgr_strtond(), posix_spawn(), posix_spawnp(), putenv(), setenv(), sigaddset(), sigdelset(), sigemptyset(), sigfillset(), spawnl(), spawnle(), spawnlp(), spawnlpe(), spawnp(), spawnv(), spawnve(), spawnvp(), spawnvpe(), wait(), waitpid()




Предыдущий раздел: Описание API системной библиотеки