2015-08-23 2 views
1

Я читал о принципе копирования на запись, который возникает, когда новый процесс разветвляется в Linux.Как сегмент кода делится между процессами в Linux?

Я также прочитал о том, что, если несколько экземпляров одной программы работают одновременно, в памяти может быть найден только один экземпляр программного кода.

Мне было интересно, является ли это прямым следствием принципа копирования на запись или нет, а если нет, то каков процесс, который гарантирует отсутствие лишних копий кода программы в памяти?

ответ

3

мне было интересно, является ли это прямым следствием копирования при записи принцип или не

Нет, это не. FWIW, вы могли бы разделять сегменты кода без COW, и вы могли бы иметь COW без разделяемых сегментов кода. Это независимо.

Если общий код программы должен был быть достигнут вследствие COW, то от этого могут выиграть только связанные процессы.

Например, если процесс A вилок дважды и создает процессы B и C, а затем B и C вызов один из семи exec функций на двоичный код, то вы могли сказать, что сегмент кода разделяется из-за COW - так как сегмент кода никогда не записывается во время выполнения и отображается только для чтения, то он должен быть автоматически общим, не так ли?

Что делать, если вы запускаете тот же исполняемый файл из другой оболочки? (Или какие-то другие несвязанные процессы вилки и выполняет одну и ту же программу? Это не обязательно должна быть оболочка ...)

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

Вместо этого сегмент кода используется совместно с файлами с отображением памяти. При загрузке нового исполняемого файла в память вызывается mmap(2) для отображения содержимого двоичного файла в память.

и если это не так, то, что это процесс, который гарантирует, что никакие ненужные копии кода программы не находятся в памяти?

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

Linux, например, связывает файлы с адресными пространствами памяти с полем i_mappingstruct inode. Итак, когда mmap(2) вызывается в двоичном формате в первый раз, страницы физической памяти назначаются для хранения информации, и устанавливается поле i_mapping этого inode файла; более поздние вызовы будут использовать поле i_mapping и поймут, что существует такое адресное пространство, связанное с этим inode, и потому что оно доступно только для чтения, а физические страницы не выделяются, поэтому все заканчивается совместным использованием. Обратите внимание, что виртуальная память может отличаться в каждом процессе, хотя она относится к одной и той же физической странице (что означает, что ядро ​​будет по меньшей мере распределять и обновлять таблицы страниц каждого процесса, но это о нем).

The inode structure is defined in fs.h - Я могу только догадываться, что другие варианты UNIX делают это аналогичным образом.

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

2

Обмен программным кодом (иногда называемым программным текстом) основан на другом механизме: Память сопоставленных файлов.

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

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

Хорошее место, чтобы узнать больше это Modern Operating Systems Эндрю Таненбаум

Смежные вопросы