Почему в Unix есть fork (), а не CreateProcess ()? - PullRequest
12 голосов
/ 15 октября 2011

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

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

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

Ответы [ 3 ]

11 голосов
/ 15 октября 2011

Вызова 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 (перейдите по ссылкам «См. Также» внизу справочной страницы, на которую ссылаются).

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


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

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

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

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

3 голосов
/ 15 октября 2011

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

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

Я уверен, что в Windows есть такая полезная ForkProcess: (

Удачного кодирования.


Упомянутый cnicutar, Copy-On-Write (COW) - одна из используемых стратегий.

0 голосов
/ 23 марта 2015

Есть функция, которая эквивалентна forkexec - система

http://www.tutorialspoint.com/c_standard_library/c_function_system.htm

#include <stdio.h>
#include <string.h>

int main ()
{
  char command[50];

  strcpy( command, "ls -l" );
  system(command);

  return(0);
} 
...