При вызове fork(), ядро операционной системы создает новый процесс, дочерний процесс, который является почти точной копией родительского процесса.
С точки зрения памяти происходит следующее:
Виртуальное адресное пространство: Дочерний процесс получает собственное, отдельное виртуальное адресное пространство, идентичное родительскому на момент вызова fork(). Это означает, что дочерний процесс "видит" те же диапазоны адресов и имеет ту же структуру сегментов (код, данные, стек, куча), что и родительский.
Физическая память и Copy-on-Write (CoW): Изначально дочерний и родительский процессы совместно используют одни и те же страницы физической памяти. Это оптимизация, известная как "Copy-on-Write" (CoW). Физическая память копируется только тогда, когда один из процессов пытается изменить содержимое страницы.
Дескрипторы файлов: Открытые дескрипторы файлов наследуются дочерним процессом. Оба процесса совместно используют указатели на смещение в файле.
Другие ресурсы: Другие ресурсы, такие как сигнальные обработчики, текущая рабочая директория и т.д., также копируются или наследуются.
Вот упрощенная иллюстрация:
До fork():
plaintext
Сразу после fork() (CoW):
plaintext
После записи одной из страниц (CoW сработал):
plaintext
Важно понимать, что несмотря на одинаковое виртуальное адресное пространство сразу после fork(), любые изменения в памяти одного процесса (запись в переменные, выделение/освобождение памяти в куче) не влияют на память другого процесса благодаря механизму CoW. Это полностью независимые процессы.