Яка різниця між fork () та vfork ()?


13

Я хотів би детально розібратися в різниці між fork () та vfork (). Я не зміг повністю перетравити сторінку людини.

Я також хотів би уточнити коментар одного з моїх колег: " У поточному Linux немає vfork (), навіть якщо ви його зателефонуєте, він буде внутрішньо викликати fork () ."

Відповіді:


24

Сторінки людини, як правило, є стислими довідковими документами. Вікіпедія - це краще місце для звернення до концептуальних пояснень.

Fork дублює процес: він створює дочірній процес, який майже ідентичний батьківському процесу (найбільш очевидною відмінністю є те, що новий процес має інший ідентифікатор процесу). Зокрема, fork (концептуально) повинен копіювати всю пам'ять батьківського процесу.

Оскільки це досить дорого, vfork був винайдений для обробки звичайного особливого випадку, коли копія не потрібна. Найчастіше перше, що робить дочірній процес - це завантаження нового зображення програми, тому це відбувається:

if (fork()) {
    # parent process …
} else {
    # child process (with a new copy of the process memory)
    execve("/bin/sh", …);  # discard the process memory
}

У execveзавантажує виклик новий виконуваний файл програми, і це замінює код і дані процесу пам'яті кодом нового виконуваного файлу і свіжій пам'яті даних. Так вся копія пам'яті, створена компанією, forkбула взагалі ні за що.

Таким чином vforkвиклик був винайдений. Це не робить копію пам'яті. Тому vforkце дешево, але його важко використовувати, оскільки ви повинні переконатися, що ви не маєте доступу до будь-якого з стекових процесів або купі простору в дочірньому процесі. Зауважте, що навіть читання може бути проблемою, оскільки батьківський процес продовжує виконуватись. Наприклад, цей код порушений (він може працювати, а може і не працювати, залежно від того, отримує дитина або батько спочатку часовий відрізок):

if (vfork()) {
    # parent process
    cmd = NULL; # modify the only copy of cmd
} else {
    # child process
    execve("/bin/sh", "sh", "-c", cmd, (char*)NULL);  # read the only copy of cmd
}

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

Linux зберігає vfork. forkСистемний виклик повинен ще зробити копію віртуальної таблиці ходу пам'яті, навіть якщо він не копіює фактичну пам'ять; vforkнавіть не потрібно цього робити. У більшості застосувань поліпшення продуктивності незначно.


1
Дякуємо за цю блискучу відповідь. Працюючи fork (), дитина все одно збирається отримати новий ідентифікатор процесу та пов'язаний з ним Віртуальний простір, то навіщо йому все-таки робити копію таблиці віртуальної пам'яті процесу? Мені не ясно в цій частині.
Сен

@Sen: forkпотрібно створити окреме віртуальне відображення пам’яті, щоб наступні копії копіювання при записі впливали лише на один із двох процесів.
Жил "ТАК - перестань бути злим"

Ви впевнені, що батьківський процес працює?
qbolec

2

fork()І vfork()системні виклики різні.

Система fork()виклику генерує два однакових процеси з окремою пам'яттю. Система vfork()виклику генерує два процеси, які поділяють одну і ту ж пам’ять.

З vfork()батьком буде чекати, коли дитина закінчиться. Батько успадковує змінні, якими обмінюється програма. Тож після виклику дитини всі змінні, модифіковані всередині дитини, все ще будуть модифіковані всередині батьків.

Для отримання додаткової інформації натисніть тут

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