Как копирование при записи в fork() обрабатывает несколько форков?

Согласно википедии (что может быть неправильно)

Когда выполняется системный вызов fork(), создается копия всех страниц, соответствующих родительскому процессу, загружаемая ОС в отдельную область памяти для дочернего процесса. Но в некоторых случаях это не требуется. Рассмотрим случай, когда дочерний процесс выполняет системный вызов exec (который используется для выполнения любого исполняемого файла из программы на C) или завершает работу вскоре после fork(). Когда дочерний процесс необходим только для выполнения команды родительского процесса, нет необходимости копировать страницы родительского процесса, поскольку exec заменяет адресное пространство вызвавшего его процесса командой, которую необходимо выполнить.

В таких случаях используется метод, называемый копированием при записи (COW). С помощью этого метода, когда происходит разветвление, страницы родительского процесса не копируются для дочернего процесса. Вместо этого страницы совместно используются дочерним и родительским процессом. Всякий раз, когда процесс (родительский или дочерний) изменяет страницу, для этого процесса (родительского или дочернего), который выполнил модификацию, создается отдельная копия только этой конкретной страницы. Затем этот процесс будет использовать только что скопированную страницу, а не общедоступную во всех будущих ссылках. Другой процесс (тот, который не изменил общую страницу) продолжает использовать исходную копию страницы (которая теперь не является общей). Этот метод называется копированием при записи, поскольку страница копируется, когда какой-либо процесс записывает на нее.

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

Мой вопрос: что произойдет, если вилка будет вызвана несколько раз, прежде чем какой-либо процесс предпримет попытку записи на общую страницу?


person ssgao    schedule 11.12.2012    source источник
comment
что может быть не так, это неправда, так это происходит по крайней мере в одном крупномасштабном развертывании высокой доступности, о котором я знаю. большой масштаб составляет около 30 000 процессоров, разветвляющих около 20 000 дочерних элементов.   -  person g24l    schedule 20.12.2015


Ответы (2)


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

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

person perreal    schedule 11.12.2012
comment
Спасибо perreal, я думаю, что первая часть ответа выглядит так же, как у Ричи. У меня тот же вопрос, где в linux хранится счетчик ссылок? Лучший способ, который я могу придумать, это хранить его на пте, но там явно не хватает места. - person ssgao; 11.12.2012
comment
это в task->mm->map_count - person perreal; 11.12.2012

Исходная страница помечается как доступная для записи только в том случае, если она принадлежит одному процессу, что может быть не так, если было несколько ответвлений. Новая страница всегда помечается как доступная для записи, потому что она принадлежит только процессу, который пытался ее записать.

person rici    schedule 11.12.2012
comment
Привет Ричи, спасибо за ответ. Так как же Linux отслеживает, сколько виртуальных адресов сопоставляется с общей страницей? - person ssgao; 11.12.2012
comment
он ведет счетчик ссылок. В конце концов, он полностью отвечает за распределение страниц, так что это не сложно. В любом случае, он должен знать, когда завершается последний потребитель страницы. - person rici; 11.12.2012
comment
Извините за конкретику, но могу я спросить, где хранится этот счетчик ссылок в Linux? - person ssgao; 11.12.2012
comment
@hydrology Хранится на странице структуры, см. lxr.linux. нет/linux+v3.6.10/include/linux/mm_types.h - person rici; 11.12.2012