
Дебати в ядрі Linux: заміна fork() + exec() на spawn templates
Лі Чен запропонував додати до ядра Linux «spawn templates» — шаблони запуску процесів. У поточному вигляді їх не приймуть, але дискусія може дати Linux повноцінний posix_spawn().
Від найдавніших часів Unix створення процесів спирається на два системні виклики: fork(), який створює дочірній процес як копію батьківського, та exec(), який запускає нову програму замість поточної. У ядрах Linux вони відоміші як clone() і execve(), але модель не змінилася. Нещодавня пропозиція Лі Чена додати до ядра «spawn templates» обговорювалася в списку розсилки ядра: у поточному вигляді її не приймуть, але вона може вказати шлях до нового примітиву створення процесів.
Ціна fork() із наступним exec()
fork() — відносно дорогий системний виклик: ядро має скопіювати для дочірнього процесу весь його стан, включно з пам'яттю. За роки зроблено чимало оптимізацій, але fork залишається принципово затратним — а в типовому шаблоні за ним одразу йде exec(), який відкидає щойно скопійовану пам'ять. vfork() був ранньою спробою оптимізувати саме цей випадок, проте послідовність усе ще дорожча, ніж могла б бути.
Шаблони запуску й кешована підготовка
Набір патчів Чена орієнтований на застосунки, які багаторазово запускають один і той самий виконуваний файл — наприклад, програму, що раз за разом викликає Git, щоб отримати дані про репозиторій. Такий застосунок може створити шаблон новим системним викликом spawn_template_create(), який повертає дескриптор файла, заданого або дескриптором (execfd), або абсолютним шляхом (filename), але не обома одразу. Ядро відкриває файл і кешує інформацію, що дозволяє надалі запускати його швидше.
Кожен запуск описується структурою spawn_template_spawn_args: argv указує на список аргументів, envp — на середовище, а actions — на масив записів spawn_template_action, які керують дескрипторами та обробкою сигналів. Закриття четвертого дескриптора в дочірньому процесі, наприклад, задається дією типу SPAWN_TEMPLATE_ACTION_CLOSE з fd рівним чотирьом. Далі процес запускають через spawn_template_spawn(), який внутрішньо йде близько до звичайного шляху fork()/exec() і зберігає всі перевірки; швидкість дає саме кеш. У результатах бенчмарків із супровідного листа приріст становить близько 2%.
Рецензенти: проблема — у частині fork()
Найдокладніший відгук опублікував Матеуш Гузік: «Уся ідіома fork + exec жахлива і має піти з ужитку». Він зауважив, що набір патчів не торкається частини з fork(), хоча саме там основні витрати, і що «створення чистого процесу — правильний шлях». Крістіан Браунер поставився до мети схвально — «Ідея builder API для exec не така вже й божевільна» — але запропонував будувати новий інтерфейс на наявній абстракції pidfd: опція до pidfd_open() створювала б порожній процес, а серія викликів нового pidfd_config() налаштовувала б його середовище та образ для виконання — за аналогією з fsconfig().
Ключова мета Браунера — підтримка реалізації posix_spawn() у просторі користувача. posix_spawn() добре підходить на заміну шаблону fork()/exec(), і розробники, ймовірно, вітали б нативну реалізацію, яка, на відміну від поточної, не ховає fork() та exec() під капотом. Чен погодився, що окреслений Браунером API виглядає краще, і сказав, що подальша робота піде в цьому напрямку. Тож spawn templates у ядрі Linux не з'являться — натомість Linux може нарешті отримати повноцінну реалізацію posix_spawn().
SiTech — веброзробка з підтримкою AI
Створюємо швидкі та сучасні сайти й інтегруємо AI у бізнес-процеси. Маєте проєкт чи запитання? Із задоволенням допоможемо.