2011-10-15 2 views
12

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

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

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

ответ

11

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), это нормально, если вы хотите отключить эту функцию перед запуском другой программы. Опираясь на другую программу, чтобы знать, что делать, это ... глупо.

+0

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

+0

hmm, так что вы говорите, что проще с fork() - exec() сделать такие вещи (перенаправление i/o, возврат привилегий и т. Д.), Я понял? –

+1

Да: по сравнению с искажениями, необходимыми для 'posix_spawn()', гораздо проще использовать 'fork()', а затем выполнить дочерние действия, необходимые ему, перед использованием 'exec()'. Прочтите обоснование 'posix_spawn()'; это довольно просвещает (или, по крайней мере, это было для меня). Список вещей, которые вы можете сделать с 'posix_spawn()', впечатляет, но он также более сложный, чем предоставляет 'fork()'. –

3

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

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

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

Днем кодирования.


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

+2

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

+0

@Ali Veli Современные вилки не дублируют процесс вообще. Посмотрите «копировать на запись». – cnicutar

+0

позволяет сказать, что я создам новый процесс. c-o-w или нет, вилка что-то делает правильно? поэтому я думаю, что если я просто создам новый процесс, я бы не сделал этого (даже если это всего лишь 1 инструкция). –