Действительно ли fork () копирует всю кучу процесса в Linux?

Системный вызов fork() клонирует дочерний процесс из текущего процесса. Эти два процесса идентичны, за исключением их PID.

Естественно, если процессы просто читают из своих куч, а не пишут на него, копирование кучи будет огромной тратой памяти.

Является ли копия всего процесса копией? Оптимизирован ли он таким образом, что только запись запускает кучу?

Полностью fork() реализуется с использованием mmap / copy при записи.

Это не только влияет на кучу, но и разделяет библиотеки, стек, области BSS.

Что, кстати, означает, что fork – чрезвычайно легкая операция, пока результирующие 2 процесса (родительский и дочерний) фактически не начнут записывать в диапазоны памяти. Эта особенность является одним из основных факторов, влияющих на летальность вилок-бомб – вы оказываете слишком много процессов, прежде чем ядро ​​будет перегружено репликацией и дифференциацией страниц.

Вам будет трудно найти в современной ОС пример операции, в которой ядро ​​выполняет печать на жестком диске (исключение драйверов устройств) – гораздо проще и эффективнее использовать функции виртуальной машины.

Даже execve() по существу «пожалуйста, mmap binary / ld.so / whatnot, а затем выполнить» – и виртуальная машина обрабатывает фактическую загрузку процесса в ОЗУ и выполнение. Локальные неинициализированные переменные заканчиваются на «нулевой странице» – специальная страница только для чтения с записью, содержащая нули, локальные инициализированные переменные в конечном итоге становятся mmaped (copy-on-write, again) из самого двоичного файла, и т.п.

Ядро Linux реализует Copy-on-Write при вызове fork() . Когда выполняется syscall, страницы, на которых родительский и дочерний ресурсы отмечены только для чтения.

Если запись выполняется на странице только для чтения, она затем копируется, так как память больше не идентична между двумя процессами. Поэтому, если выполняются только операции чтения, страницы не будут скопированы вообще.

Linux делает Copy-on-Write. Поскольку fork создает новый процесс, выделенные страницы помечены как readonly и разделяются между родителем и дочерним элементом. Когда один из них пытается изменить страницу, создается сбой страницы, что приводит к копированию страницы и правильной настройке таблицы страниц.