Вся ли память, помеченная как копируемая при записи, копируется после единственного изменения одной части данных?

Мой вопрос, возможно, плохо сформулирован и проистекает из моего дилетантского понимания управления памятью.

Меня беспокоит следующее: у меня есть Perl-скрипт, который многократно разветвляется. Насколько я понял из страницы форка в perldoc, реализуется копирование при записи. Затем каждый из потомков вызывает system(), снова разветвляясь, чтобы вызвать внешнюю программу. Данные из внешней программы считываются обратно в дочернюю программу и выгружаются в виде хранимого файла, который должен быть собран и обработан родительской программой после выхода всех дочерних элементов.

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

Но с другой стороны, копирует ли копирование при записи только наименьший фрагмент памяти, содержащий необходимые данные? Тогда что же это за кванты памяти? Как устанавливается его размер?

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


person EMiller    schedule 19.01.2011    source источник


Ответы (2)


Память организована в виде страниц, обычно по 4 КБ каждая (для этого могут быть установлены разные значения, и они зависят от аппаратного обеспечения, но это норма на платформах Intel со стандартными операционными системами). Когда дочерний процесс записывает на страницу копирования при записи, он будет скопирован.

person EmeryBerger    schedule 19.01.2011

Да, разветвление увеличит объем используемой памяти. Если это проблема, используйте такой модуль, как Parallel::ProcManager или Forks::Super, который может регулировать количество активных фоновых процессов. Ограничение количества активных ответвлений также является хорошей идеей, когда ваши процессы привязаны к процессору, вводу-выводу или потенциально могут чрезмерно использовать любой другой ограниченный ресурс на вашем компьютере.

use Forks::Super MAX_PROC => 10, ON_BUSY => block;

...
$pid = fork();        # blocks if there are already 10 child processes
...                   # unblocks when one of the children finishes
person mob    schedule 19.01.2011
comment
Спасибо. Forks::Super отлично выглядит. - person EMiller; 20.01.2011
comment
Однако будьте осторожны - можно создать взаимоблокировки, блокируя создание новых процессов, если, например, родительский процесс ожидает дочерний процесс (который никогда не запускается из-за ограничения количества процессов). - person EmeryBerger; 20.01.2011
comment
Если дочерний процесс не запущен, значит, у него нет идентификатора процесса, и вы не можете его дождаться. Пока существующие дочерние процессы в конечном итоге завершатся, это не приведет к взаимоблокировке. - person mob; 20.01.2011
comment
Я должен был быть более ясным: вы можете застрять, если дочерний процесс должен выполнить какую-то работу для продолжения родительского процесса, а дочерний процесс никогда не запускается. - person EmeryBerger; 20.01.2011