Чтение онлайн

на главную - закладки

Жанры

QNX/UNIX: Анатомия параллелизма
Шрифт:

pclose(f);

return EXIT_SUCCESS;

}

Примечание

Новый процесс выполняется с тем же окружением, что и родительский. Процесс, указанный в команде, запускается примерно следующим эквивалентом:

spawnlp(P_NOWAIT, shell_command, shell_command, "-с", command, (char*)NULL);

где

shell_command
— командный интерпретатор, специфицированный переменной окружения SHELL или утилита
/bin/sh
. В этом кроется причина возможного различия в выполнении вызовов
system
и
popen
.

Если

popen
возвращает
не
NULL
, то выполнение прошло успешно. В противном случае устанавливается
errno
:
EINVAL
— недопустимый аргумент
mode
,
ENOSYS
— в системе не выполняется программа менеджера каналов. После завершения работы с каналом, созданным
popen
, он должен быть закрыт парной операцией
pclose
.

При использовании

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

Клонирование процесса

Вызов

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

#include <process.h>

pid_t fork(void);

Действие вызова

fork
следующее:

• Порождается дочерний процесс, которому системой присваивается новое уникальное значение PID.

• Дочерний процесс получает собственные копии файловых дескрипторов, открытых в родительском процессе в точке выполнения

fork
. Каждый дескриптор ссылается на тот же файл, который соответствует аналогичному дескриптору родителя. Блокировки файлов (locks), установленные в родительском процессе, наследуются дочерним процессом.

• Для дочернего процесса его значения

tms_utime
,
tms_stime
,
tms_cutime
и
tms_cstime
устанавливаются в значение ноль. Выдержки (alarms) для этих таймеров, установленные к этому времени в родительском процессе, в дочернем процессе очищаются.

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

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

errno
:
EAGAIN
— недостаточно системных ресурсов;
ENOMEM
— процессы требуют большее количество памяти, чем доступно в системе;
ENOSYS
— функция
fork
не реализуется в этой модели памяти, например в физической модели адресации памяти (напомним, что QNX — многоплатформенная ОС и число поддерживаемых ею
платформ все возрастает).

А вот с кодом возврата этой функции в случае удачи сложнее и гораздо интереснее. Дело в том, что для одного вызова

fork
одновременно имеют место два возврата в двух различных копиях (но в текстуально едином коде!): в копии кода, соответствующей дочернему процессу, возвращается 0, а в копии кода родителя — PID успешно порожденного дочернего процесса. Это и позволяет разграничить в едином программном коде фрагменты, которые после точки ветвления надлежит выполнять в родительском процессе и которые относятся к дочернему процессу. Типичный шаблон кода, использующего
fork
, выглядит примерно так:

pid_t pid = fork;

if (pid == -1) perror("fork"), exit(EXIT_FAILURE);

if (pid == 0) {

// ... этот код выполняется в дочернем процессе ...

exit(EXIT_SUCCESS);

}

if (pid > 0) {

// ... этот код выполняется в родительском процессе ...

do { // ожидание завершения порожденного процесса

wpid = waitpid(pid, &status, 0);

} while(WIFEXITED(status) == 0);

exit(WEXITSTATUS(status));

}

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

fork
. Заметьте, что во всех многозадачных ОС обязательно присутствует та или иная техника программного создания нового процесса, однако не во всех существует техника именно клонирования, то есть создания полного дубликата порождающего процесса.

Вот как выглядит простейший ретранслирующий TCP/IP-сервер, заимствованный из нашей более ранней публикации [4] (обработка ошибок полностью исключена, чтобы упростить пример):

Ретранслирующий TCP/IP-сервер [12]

int main(int argc, char* argv[]) {

// создание и подготовка прослушивающего сокета:

int rc, ls = socket(AF_INET, SOCK_STREAM, 0);

setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, &rc, sizeof(rc));

12

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

struct sockaddr_in addr;

memset(&addr, 0, sizeof(addr));

addr.sin_len = sizeof(addr); // специфика QNX

addr.sin_family = AF_INET;

addr.sin_port = htons(PORT); // PORT - константа

addr.sin_addr.s_addr = htonl(INADDR_ANY);

bind(ls, (struct sockaddr*)&addr, sizeof(sockaddr));

listen(ls, 25);

Поделиться:
Популярные книги

70 Рублей

Кожевников Павел
1. 70 Рублей
Фантастика:
фэнтези
боевая фантастика
попаданцы
постапокалипсис
6.00
рейтинг книги
70 Рублей

Переписка 1826-1837

Пушкин Александр Сергеевич
Документальная литература:
публицистика
5.00
рейтинг книги
Переписка 1826-1837

Морской волк. 1-я Трилогия

Савин Владислав
1. Морской волк
Фантастика:
альтернативная история
8.71
рейтинг книги
Морской волк. 1-я Трилогия

Экзорцист: Проклятый металл. Жнец. Мор. Осквернитель

Корнев Павел Николаевич
Фантастика:
фэнтези
героическая фантастика
5.50
рейтинг книги
Экзорцист: Проклятый металл. Жнец. Мор. Осквернитель

Честное пионерское! Часть 4

Федин Андрей Анатольевич
4. Честное пионерское!
Фантастика:
попаданцы
альтернативная история
6.00
рейтинг книги
Честное пионерское! Часть 4

Здравствуйте, я ваша ведьма! Трилогия

Андрианова Татьяна
Здравствуйте, я ваша ведьма!
Фантастика:
юмористическая фантастика
8.78
рейтинг книги
Здравствуйте, я ваша ведьма! Трилогия

Мое ускорение

Иванов Дмитрий
5. Девяностые
Фантастика:
попаданцы
альтернативная история
6.33
рейтинг книги
Мое ускорение

Прорвемся, опера! Книга 2

Киров Никита
2. Опер
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прорвемся, опера! Книга 2

Невеста напрокат

Завгородняя Анна Александровна
Любовные романы:
любовно-фантастические романы
6.20
рейтинг книги
Невеста напрокат

Если твой босс... монстр!

Райская Ольга
Любовные романы:
любовно-фантастические романы
5.50
рейтинг книги
Если твой босс... монстр!

Приватная жизнь профессора механики

Гулиа Нурбей Владимирович
Проза:
современная проза
5.00
рейтинг книги
Приватная жизнь профессора механики

Попытка возврата. Тетралогия

Конюшевский Владислав Николаевич
Попытка возврата
Фантастика:
альтернативная история
9.26
рейтинг книги
Попытка возврата. Тетралогия

Измена. Отбор для предателя

Лаврова Алиса
1. Отбор для предателя
Фантастика:
фэнтези
5.00
рейтинг книги
Измена. Отбор для предателя

Аргумент барона Бронина 3

Ковальчук Олег Валентинович
3. Аргумент барона Бронина
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Аргумент барона Бронина 3