При fork() в Linux создается новый процесс (потомок), который является почти точной копией родительского процесса. С памятью происходит следующее:
- Копирование (пока нет): Изначально, вместо полного копирования всего адресного пространства родителя, используется механизм "копирования при записи" (copy-on-write, CoW).
- CoW: Страницы памяти родительского процесса помечаются как доступные только для чтения как для родителя, так и для потомка. Оба процесса совместно используют одни и те же физические страницы.
- Изменение: Только при попытке одного из процессов (родителя или потомка) записать данные на такую общую страницу, ядро Linux выделяет новую физическую страницу, копирует туда содержимое оригинальной страницы и перенаправляет виртуальный адрес этого процесса на новую физическую страницу. Страница родителя остается неизменной.
- Разделяемая память: Сегменты разделяемой памяти (например, System V Shared Memory или POSIX Shared Memory) не дублируются. Оба процесса получают доступ к одному и тому же физическому сегменту разделяемой памяти.
- Файловые дескрипторы: Таблица файловых дескрипторов копируется. Это означает, что потомок имеет доступ к тем же открытым файлам, что и родитель, с той же позицией указателя файла. Однако, закрытие дескриптора одним процессом не влияет на другой.
- Стек: Стек текущего потока в родительском процессе копируется для потомка, чтобы он мог продолжить выполнение с того же места.
- Куча (Heap): Куча родительского процесса также подпадает под механизм CoW.
Таким образом, fork() эффективен, так как полное копирование памяти происходит только при необходимости изменения данных, что экономит время и системные ресурсы.