Когда сами вызывать fork () и exec ()?

9

Я изучаю команды fork () и exec (). Кажется, что fork () и exec () обычно вызываются вместе. (fork () создает новый дочерний процесс, а exec () заменяет текущий образ процесса новым.) Однако в каких случаях вы можете вызывать каждую функцию отдельно? Есть ли такие сценарии?

Квил
источник
2
Традиционная вилка: while (1) fork (); захватить системные ресурсы.
Джошуа

Ответы:

22

Конечно! Обычный шаблон в программах-оболочках - это делать разные вещи, а затем заменять себя другой программой, используя только execвызов (без разветвления).

#!/bin/sh
export BLAH_API_KEY=blub
...
exec /the/thus/wrapped/program "$@"

Пример из реальной жизни это GIT_SSH(хотя git(1)также предлагает, GIT_SSH_COMMANDесли вы не хотите делать вышеупомянутый метод программы-оболочки).

Только для httpdразветвления используется при порождении множества обычно рабочих процессов (например, Apache в режиме разветвления (хотя только разветвление лучше подходит для процессов, которые должны перегружать ЦП, а не для процессов, которые трясут, ожидая сетевого ввода-вывода) ) или для разделения привилегий, используемых sshdдругими программами в OpenBSD (без exec)

$ doas pkg_add pstree
...
$ pstree | grep sshd
 |-+= 70995 root /usr/sbin/sshd
 | \-+= 28571 root sshd: jhqdoe [priv] (sshd)
 |   \-+- 14625 jhqdoe sshd: jhqdoe@ttyp6 (sshd)

У rootsshd на клиентском соединении разветвленная копия (28571), а затем еще одна копия (14625) для разделения привилегий.

thrig
источник
14

Есть много.

Программы, которые вызывают fork()без exec(), обычно следуют шаблону порождения дочерних рабочих процессов для выполнения различных задач в отдельных процессах по отношению к основному. Вы найдете это в программах столь же разнообразны , как dhclient, php-fpmи urxvtd.

Программа , которая требует exec()не fork()является последовательной загрузкой , накладывая свой процесс с другой программой изображением. Существует целая субкультура утилит цепной загрузки, которые выполняют определенные действия для обработки состояния, а затем выполняют другую программу для запуска с этим измененным состоянием процесса. Такие утилиты распространены в наборе инструментов семейства сервисов и управления системой daemontools, но не ограничиваются ими. Несколько примеров:

В Daemontools семья наборов инструментов есть много таких инструментов, с machineenvпомощью find-matching-jvmк runtool.

JdeBP
источник
2

В дополнение к другим ответам, отладчики, использующие ptrace, обычно используют разрыв между forkи exec. Отладчик должен пометить себя, PTRACE_TRACEMEчтобы указать, что он отслеживается его родительским процессом - отладчиком. Это должно дать необходимые разрешения отладчику.

Таким образом, отладчик сначала сам разветвляется. Ребенок позвонит ptraceс, PTRACE_TRACEMEа затем позвонит exec. В зависимости от того, какая программа дочернего исполнителя будет отслеживаться родителем.

bytefire
источник
Существует множество примеров работы между fork и exec, наиболее распространенным из которых является перенаправление ввода / вывода (например, настройка каналов). Но вопрос в том, чтобы сделать fork без какого-либо exec вообще.
Бармар
0

Exec без вилки

Есть по крайней мере две причины, почему вы хотели бы сделать такую ​​вещь:

  1. Цепная загрузка. Текущий образ процесса заменяется чем-то другим.
  2. Перезапуск работающей в данный момент программы (например, может произойти, когда вы SIGHUP или такой процесс на сервере, перезагрузите все и сделаете новый старт). В некотором смысле, можно утверждать, что это цепная загрузка, только по совпадению с той же самой программой.

вилка без exec

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

Другое распространенное использование - это разветвление детей-работников, которое стало известным благодаря веб-серверу apache около 25 лет назад (в настоящее время это больше не считается современным из-за того, что оно очень склонно к проблеме стада грома, но оно, безусловно, обеспечивает чертовски простой, самый надежный сервер из всех возможных).

Еще одно распространенное использование - создание последовательного снимка. forkне только создает процесс, но и копирует (теоретически, на самом деле он только помечает страницы, копируемые при записи) адресное пространство. Это (атомарно) создает снимок полных данных программы, которые родительский объект больше не может изменять.
Некоторые программы используют это преимущество. Например, Redis сохраняет данные на диск (в согласованном состоянии), одновременно изменяя набор данных одновременно. Это работает только потому, что forkсоздан непротиворечивый снимок, который не видит изменений, внесенных родительским процессом.

Damon
источник
На самом деле в наши дни очень мало демонов, большинство из которых не делают этого в стандартном режиме или не используют обычно используемый режим. Это ошибка, приводящая к несоответствию и ужасам готовности , и является одной из ошибок ошибки одомонизации . Эта ошибка наконец-то широко распалась.
JdeBP