Чому розвивається механізм створення процесу за замовчуванням?


46

Системний виклик UNIX для створення процесу fork () створює дочірній процес шляхом копіювання батьківського процесу. Я розумію, що за цим майже завжди супроводжується викликом до exec () для заміни дочірнього простору пам’яті (включаючи текстовий сегмент). Копіювання батьківського простору пам’яті у fork () для мене завжди здавалося марнотратним (хоча я розумію, що відходи можна звести до мінімуму, зробивши сегменти пам’яті копіюванням на запис, так що копіюються лише покажчики). У будь-якому разі, хтось знає, чому такий підхід дублювання необхідний для створення процесу?


3
Зауважте, що на fork(2)сторінці man під Linux йдеться: Under Linux, fork() is implemented using copy-on-write pages, so the only penalty that it incurs is the time and memory required to duplicate the parent's page tables, and to create a unique task structure for the child. я уявляю (але точно не знаю), що це стосується інших сучасних ароматів Unix.
larsks

4
Оригінал PDP-11 Unix дійсно справді копіював усі байти роздвоєного процесу: але він мав лише 64 Кб виконуваного файлу та щонайбільше 64 Кб даних, тому це не було великим тягарем навіть у 1975 році. здогадуйтесь, що ВСЕ unix та unix-a-like приблизно з 1990 року мали текстові сегменти з копією на запис, тому я навіть не впевнений, чому книги та статті більше не поширюють "проблему з роботою з вилкою".
Брюс Едігер

У наш час fork реалізований аналогічно vfork ( openbsd.org/cgi-bin/… ). Це ефективно, не хвилюйтесь.
Акі

Також зауважте, що існує велика кількість застосувань, коли ви не виконуєте після вилки (або, принаймні, не виконуєте відразу): подумайте про труби та веб-сервери.
jfg956

Ви можете сказати, що це буде повільно. Але як говорить @cjm, подивіться на альтернативні можливості Microsoft, які використовують CreateProcess, їм довелося реалізувати потоки рано (можливо, це єдине, на що вони ведуть), оскільки CreateProcess повільний. (Їм також потрібні були нитки, тому що selectбуло зламано, але це вже інша історія).
ctrl-alt-delor

Відповіді:


57

Це спростити інтерфейс. Альтернативою forkі execбуде щось подібне до функції CreateProcess Windows . Зауважте, скільки параметрів CreateProcessмає, і багато з них - це структури з ще більшою кількістю параметрів. Це тому, що все, що ви хочете контролювати щодо нового процесу, має бути передано CreateProcess. Насправді CreateProcessне вистачає параметрів, тому Microsoft довелося додати CreateProcessAsUser та CreateProcessWithLogonW .

У fork/execмоделі вам не потрібні всі ці параметри. Натомість певні атрибути процесу зберігаються впоперек exec. Це дозволяє вам fork, а потім змінити будь-які атрибути процесу, які ви хочете (використовуючи ті самі функції, які ви використовували нормально), а потім exec . У Linux forkнемає параметрів і execveмає лише 3: програму, яку потрібно запустити, командний рядок для її надання та її оточення. (Є й інші execфункції, але вони просто обгортки, що execveнадаються бібліотекою С для спрощення випадків звичайного використання.)

Якщо ви хочете , щоб почати процес з інших поточних каталогом: fork, chdir, exec.

Якщо ви хочете Перенаправлення STDIN / STDOUT: fork, закриття / відкриті файли, exec.

Якщо ви хочете , щоб користувачі перемикача: fork, setuid, exec.

Всі ці речі можна комбінувати за потребою. Якщо хтось придумав новий вид атрибутів процесу, вам не доведеться змінювати forkі exec.

Як зазначалося в ларках, більшість сучасних Unixes використовують копіювати при записі, тому forkце не передбачає значних витрат.


16
Відмінне пояснення. "Ті, хто не розуміє UNIX, засуджуються, щоб винаходити його погано". - Генрі Спенсер
Кайл Джонс

1
Дякую! У вас є випадковість довідки?
Еллен Спертус

1
@Aki, nope, CreateProcess () буквально створює новий процес і створює його з нуля, без розгортання.
psusi

2
Але чи не повинно бути десь еквівалента CreateProcess () десь в Unix? Інакше як створюється найперший процес? На відміну від міфологічного бога-творця, перший процес не може розвинути себе з небуття. ;-)
Стівен Понеділок,

2
@StevenMonday, так, але він знаходиться в коді ініціалізації ядра і не є доступним зовні. Він не потребує всіх цих параметрів, оскільки майже все жорстко закодовано. Він може створювати лише ідентифікатор процесу 1, так само процес init. Після цього процеси створюються лише розщепленням.
cjm

5

На додаток до відповіді cjm, Єдина специфікація Unix визначає функцію з назвою vfork(). Ця функція працює як fork, за винятком того, що процес forked має невизначене поведінку, якщо він робить щось інше, ніж спробувати викликати функцію familly exec або викликати _exit().

Таким чином, в основному єдине використання з визначеною поведінкою:

pid_t ret = vfork();
if(ret == 0)
{
    exec(...);
    _exit(EXIT_FAILURE); //in case exec failed for any reason.
}

То що ж vforkробити? Це недорого fork. У реалізаціях без копіювання при записі отриманий процес поділить простір пам’яті з початковим процесом (звідси невизначена поведінка). У реалізаціях з функцією копіювання під час запису vforkдозволено бути ідентичною fork(), оскільки реалізація копіювання при записі є швидкою.

Існує також додаткова posix_spawnфункція (і posix_spawnpфункція), яка може безпосередньо створити новий процес. (Дозволено також реалізувати їх за допомогою виклику бібліотеки, використовуючи forkта exec, і надається приклад реалізації.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.