промежуточный шаг позволяет для настройки общих ресурсов в дочернем процессе, если внешняя программа не знает об этом. Канонический пример построения трубы:
// read output of "ls"
// (error checking omitted for brevity)
int pipe_fd[2];
pipe(&pipe_fd);
if (fork() == 0) { // child:
close(pipe_fd[0]); // we don't want to read from the pipe
dup2(pipe_fd[1], 1); // redirect stdout to the write end of the pipe
execlp("ls", "ls", (char *) NULL);
_exit(127); // in case exec fails
}
// parent:
close(pipe_fd[1]);
fp = fdopen(pipe_fd[0], "r");
while (!feof(fp)) {
char line[256];
fgets(line, sizeof line, fp);
...
}
Обратите внимание, как перенаправление стандартного вывода на трубе делается в ребенка, между fork
и exec
. Конечно, для этого простого случая может быть spawning API, который просто сделает это автоматически, учитывая правильные параметры. Но дизайн fork()
позволяет произвольно манипулировать ресурсами каждого процесса в дочернем элементе - можно закрыть нежелательные файловые дескрипторы, изменить лимиты для каждого процесса, отказаться от привилегий, манипулировать сигнальными масками и т. Д. Без fork()
API для нерестовых процессов окажется либо очень жирным, либо не очень полезным.И действительно, процесс нереста вызовов конкурирующих операционных систем обычно падает где-то посередине.
Что касается ненужной памяти, то ее можно избежать с помощью метода copy on write. fork()
не выделяет новую память для дочернего процесса, а указывает ребенка на родительскую память, с инструкциями, чтобы сделать копию страницы, только если страница когда-либо была написана. Это делает fork()
не только эффективным с точки зрения памяти, но и быстрым, потому что ему нужно только скопировать «оглавление».
Клонирование может быть менее сложным, чем создание с нуля, но если мы разворачиваем с целью запуска другой программы, мы должны «exec» после fork. Этот «exec» взорвет все усилия, которые вступили в клонирование, поэтому вопрос, заданный OP, - это то, почему мы в первую очередь пытаемся клонировать? – user4815162342
@ user4815162342 Прочтите мой ответ ближе. Единственное, что заменяется на exec, адресное пространство процесса, почти не требует усилий для клонирования, поскольку это копирование при записи. Конкретный процесс обработки ядра, который действительно имеет значение, сохраняется с помощью exec. Нет никаких усилий. – jlliagre
Хорошо, я пропустил ваш последний абзац. Я все еще думаю о части «почти без усилий». Было бы интересно сравнить процесс создания forked и fork-free в одной и той же операционной системе. – user4815162342