Friday, May 18th

Last update12:13:00 PM GMT

Вы находитесь на: FreeBSD Управление памятью Дублирование адресного пространства пользователя

Дублирование адресного пространства пользователя

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

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

Методика, используемая FreeBSD для создания процессов без этих издержек, называется копирование при записи (copy-on-write). Вместо того чтобы копировать каждую страницу родительского процесса, и родительскому, и порожденному процессам, проистекающим из разветвления, даются ссылки на одни и те же физические страницы. Таблицы страниц изменяются, чтобы предотвратить изменение любым из процессов разделяемой страницы. Вместо этого, когда процесс пытается изменить страницу, осуществляется вход в ядро с отказом защиты. После определения того, что отказ был вызван попыткой модификации разделяемой страницы, ядро просто копирует страницу и изменяет поле защиты для страницы, чтобы снова разрешить изменение. Нужно копировать лишь страницы, измененные одним из процессов. Эта методика значительно повышает производительность fork, поскольку разветвляющиеся процессы обычно перекрывают порожденный процесс новым образом при выполнении exec вскоре после fork.

Следующим шагом в fork является прохождение по списку структур vm_map_entry в родителе и создание соответствующих элементов в порожденном. Каждый элемент должен быть проанализирован, и должно быть предпринято соответствующее действие.

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

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

Элементы отображения для процесса никогда не объединяются (упрощаются). Объединяться могут лишь элементы для отображения самого ядра. Элементы отображения ядра нуждаются в упрощении таким образом, чтобы избежать чрезмерного расширения. Может оказаться целесообразным сделать такое объединение элементов отображения для процесса, когда он разветвляется, особенно для больших или долгоживущих процессов.


Похожие:
Еще по теме:
Советуем прочитать:

元彼再会 恋の悩み
Сейчас 56 гостей онлайн

Реклама на сайте: