P_WAIT | Вызывающий процесс (ваша программа) будет блокирован до тех пор, пока вновь созданный процесс не отработает и не завершится. |
P_NOWAIT | Вызывающая программа не будет блокирована на время выполнения вновь созданной. Это позволяет вам запустить программу в фоновом режиме и продолжать выполнение, пока она делает свое дело. |
P_NOWAITO | Аналогично P_NOWAIT за исключением того, что устанавливается флаг SPAWN_NOZOMBIE. Это означает, что вы не должны беспокоить себя вызовом функции waitpid() для очистки кода завершения процесса. |
P_OVERLAY | Этот флаг превращает вызов функции spawn() в соответствующей вызов exec()! Ваша программа преобразуется в указанную программу без изменения идентификатора процесса ID. Вообще-то, если вы хотите сделать именно так, то, наверное, будет более корректно использовать вызов exec(), поскольку это избавит будущих читателей ваших исходных текстов от необходимости искать P_OVERLAY в справочном руководстве по библиотеке языка Си! |
Просто spawn()Как мы упомянули выше, все функции семейства spawn(), в конечном счете, вызывают базовую функцию spawn(). Ниже приведен прототип функции spawn():
#include
pid_t spawn(const char *path, int fd_count,
const int fd_map[], const struct inheritance *inherit,
char* const argv[], char* const envp[]);
Мы можем не обращать внимание на параметры path, argv, и envp — мы уже рассмотрели их выше как местоположение исполняемого модуля (path), вектор параметров (argv) и окружение (envp).
Параметры fd_count и fd_map идут вместе. Если вы задаете нуль в fd_count, тогда fd_map игнорируется, и это означает, что вновь создаваемый процесс унаследует от родительского все дескрипторы файлов (кроме тех, которые модифицированы флагом FD_CLOEXEC функции fcntl()). Если параметр fd_count имеет ненулевое значение, то он задает число дескрипторов файлов, содержащихся в fd_map, и будут унаследованы только они.
Параметр inherit — это указатель на структуру, которая содержит набор флагов, маски сигналов, и т.д. Для получения более подробной информации об этом вам следует обратиться за помощью к справочному руководству по библиотеке языка Си.
Запуск процесса при помощи функции fork()Предположим, что вы решили создать новый процесс, который был бы идентичен работающему в настоящее время процессу, и сделать это так, чтобы эти два процесса выполнялись одновременно. Вы могли бы решить эту проблему с помощью функции spawn() (и параметра P_NOWAIT), передав вновь создаваемому процессу достаточно информации о точном состоянии вашего процесса, чтобы новый процесс мог настроить себя сам. Однако, такой подход может оказаться чрезвычайно сложным, потому что описание «текущего состояния» процесса может потребовать большого количества данных.
Существует более простой способ — применение функции fork() которая просто копирует текущий процесс. У результирующего процесса как код, так и данные полностью совпадают с таковыми для родительского процесса.
Конечно же, невозможно создать процесс, который во всем был бы идентичен родительскому. Почему? Наиболее очевидное различие между этими двумя процессами должно быть в идентификаторе процесса — мы не можем создать два процесса с одним и тем же идентификатором. Если вы посмотрите документацию на функцию fork() в справочном руководстве по библиотеке Си, вы увидите, что между этими двумя процессами будет иметь место ряд различий. Внимательно изучите этот список, чтоб быть уверенным в корректном применении функции fork().
Если после ветвления по fork() получаются два одинаковых процесса, то как же их различить? Когда вы вызываете fork(), вы тем самым создаете другой процесс, выполняющий тот же самый код и в том же самом местоположении (то есть оба процесса ввернутся из вызова fork()), что и родительский. Рассмотрим пример программы: