Подтвердить что ты не робот

Почему Unix имеет fork(), но не CreateProcess()?

Я не понимаю, почему Unix имеет fork() для создания нового процесса. В Win32 API мы CreateProcess(), который создает новый процесс и загружает исполняемый файл в его адресное пространство, а затем начинает выполнение из точки входа. Однако Unix предлагает fork для создания нового процесса, и я не понимаю, почему бы мне дублировать мой процесс, если бы я хотел запустить другой процесс.

Итак, позвольте мне задать два вопроса:

  • Если fork(), а затем exec() более эффективен, почему нет функции forkexec(const char *newProc), так как мы будем называть exec() после fork() почти в каждом случае?
  • Если это не более эффективно, почему существует fork() вообще?
4b9b3361

Ответ 1

Достаточно вызова fork(). Он также более гибкий; он позволяет вам такие вещи, как настройка перенаправления ввода-вывода в дочернем процессе, а не усложнение системного вызова для создания процесса. С помощью программ SUID или SGID он позволяет ребенку потерять свои повышенные привилегии перед выполнением другого процесса.

Если вам нужен сложный способ создания процесса, найдите функцию posix_spawn().

#include <spawn.h>

int posix_spawn(pid_t *restrict pid, const char *restrict path,
        const posix_spawn_file_actions_t *file_actions,
        const posix_spawnattr_t *restrict attrp,
        char *const argv[restrict], char *const envp[restrict]);

int posix_spawnp(pid_t *restrict pid, const char *restrict file,
          const posix_spawn_file_actions_t *file_actions,
       const posix_spawnattr_t *restrict attrp,
       char *const argv[restrict], char *const envp[restrict]);

Разница заключается в том, что posix_spawnp() выполняет поиск по PATH для исполняемого файла.

Существует целый ряд других функций для обработки типов posix_spawn_file_actions_t и posix_spawnattr_t (следуйте ссылкам "См. также" внизу справочной man-страницы).

Это немного больше похоже на CreateProcess() на Windows. По большей части, однако, использование fork(), за которым вскоре следует exec(), проще.


Я не понимаю, что вы имеете в виду. Код дочернего процесса будет написан мной, так в чем разница между написанием if (fork() == 0) и помещением этого кода в начало дочернего main()?

Очень часто исполняемый код не написан вами, поэтому вы не можете изменить то, что происходит в начале дочернего процесса. Подумайте о оболочке; если только программы, которые вы запускаете из оболочки, - это те, которые вы написали, жизнь будет очень обедневшей.

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

Если вызывающая программа работает с повышенными привилегиями (привилегии SUID или SGID), обычно нужно отключить эти функции перед запуском другой программы. Опираясь на другую программу, чтобы знать, что делать, это... глупо.

Ответ 2

UNIX-подобные операционные системы (по крайней мере, более новые ядра Linux и BSD), как правило, имеют очень эффективную реализацию fork - это так "дешево", что на некоторых языках реализованы "потоковые" реализации.

В конце функция forkexec равна ~ n - для небольшого значения n-строк кода приложения.

Я уверен, что окна с пожеланиями имели такой полезный ForkProcess: (

Счастливое кодирование.


Указанный cnicutar, Copy-On-Write (COW) - одна из стратегий.