Добавлен: 29.10.2018
Просмотров: 48001
Скачиваний: 190
11.5. Управление памятью
1011
процесса. В случае совместно используемой страницы диспетчер памяти использует
элемент таблицы страниц прототипов (связанный с объектом сегмента) для заполнения
нового элемента таблицы страниц процесса.
Формат элемента таблицы страниц различается в зависимости от архитектуры про-
цессора. Для процессоров х86 и х64 элементы отображаемой страницы показаны на
рис. 11.17. Если элемент помечен как действительный, то его содержимое интерпре-
тируется аппаратным обеспечением (чтобы виртуальный адрес можно было преоб-
разовать в правильную физическую страницу). Неотображенные страницы также
имеют свои элементы, но они помечены как недействительные (invalid), и аппаратное
обеспечение игнорирует остальную часть элемента. Программный формат несколько
отличается от аппаратного и определяется диспетчером памяти. Например, для неото-
браженной страницы (которая должна быть размещена и обнулена до использования)
этот факт отмечен в элементе таблицы страниц.
Рис. 11.17. Элемент таблицы страниц (page table entry (PTE)) отображенной страницы
для архитектур Intel x86 и AMD x64
Два важных бита элемента таблицы страниц обновляются непосредственно аппа-
ратным обеспечением. Это бит доступа (А) и бит «измененная» (D). Эти биты от-
слеживают использование данного отображения страницы для доступа к странице
и возможность модифицирования страницы при этом доступе. Это реально повышает
производительность системы, поскольку диспетчер памяти может использовать бит
доступа для реализации подкачки по схеме наиболее давнего использования (Least-
Recently Used (LRU)). Принцип LRU состоит в том, что те страницы, которые дольше
всех не используются, имеют самую низкую вероятность повторного использования
в ближайшее время. Бит доступа позволяет диспетчеру памяти определить, что к стра-
нице был произведен доступ. Бит «измененная» говорит диспетчеру памяти о том,
что страница, возможно, была модифицирована (или, что более важно, она не была
модифицирована). Если страница не была модифицирована с момента считывания
с диска, то диспетчеру памяти не нужно записывать ее содержимое на диск (перед тем,
как использовать ее для чего-то другого).
В обеих архитектурах, х86 и x64, используется элемент таблицы страниц размером
64 бита (см. рис. 11.17).
Каждая страничная ошибка может быть отнесена к одной из пяти категорий:
1. Страница не зафиксирована.
2. Попытка обращения к странице с нарушением разрешений.
3. Попытка модификации страницы типа «копирование при записи».
1012
Глава 11. Изучение конкретных примеров: Windows 8
4. Необходимо увеличение стека.
5. Страница зафиксирована, но в данное время не отображена.
Первый и второй случаи — это ошибки программирования. Если программа пытается
использовать адрес, который не имеет действительного отображения, или пытается
выполнить недопустимую операцию (наподобие попытки записи в страницу «только
для чтения»), это называется нарушением доступа (access violation) и обычно приводит
к завершению процесса. Нарушение доступа часто является результатом недопусти-
мых значений указателей, в том числе результатом обращения к памяти, которая была
освобождена и откреплена от процесса.
Третий случай имеет такие же симптомы, что и второй (попытка записи в страницу
«только для чтения»), но его обработка иная. Поскольку страница была помечена как
«копирование при записи», то диспетчер памяти не выдает нарушение доступа. Вместо
этого он создает закрытую копию страницы для текущего процесса, а затем возвращает
управление тому потоку, который пытался выполнить запись в страницу. Поток повто-
ряет операцию записи, которая теперь завершится без страничной ошибки.
Четвертый случай происходит тогда, когда поток помещает значение в свой стек и по-
падает на страницу, которая еще не была выделена. Диспетчер памяти распознает это
как особый случай. Пока есть место в зарезервированных под стек виртуальных стра-
ницах, диспетчер памяти будет поставлять новые страницы, обнулять их и отображать
в процесс. Когда поток возобновит выполнение, он повторит попытку доступа, и на
этот раз она будет успешной.
И наконец, пятый случай — это нормальная страничная ошибка. Однако она имеет
несколько подвариантов. Если страница отображена на файл, то диспетчер памяти
должен просмотреть ее структуры данных (такие, как таблица страниц прототипов,
связанная с объектом сегмента), чтобы быть уверенным в том, что в памяти нет ее
копии. Если копия есть (например, в другом процессе, в резервном списке либо в спи-
ске модифицированных страниц), то он просто сделает ее совместно используемой
(возможно, что для этого ему придется пометить ее как страницу «копирование при
записи», если изменения совместно использовать не предполагается). Если копии еще
нет, то диспетчер памяти выделит свободную физическую страницу и подготовит ее
для копирования в нее страницы файла с диска, если только в этот момент не осущест-
вляется перенос с диска другой страницы (тогда нужно лишь подождать, пока этот
перенос не завершится).
Если диспетчер памяти может обработать страничную ошибку, находя нужную страни-
цу в памяти (а не считывая ее с диска), то такая ошибка называется мягкой ошибкой
(soft fault). Если нужна копия с диска, то это жесткая ошибка (hard fault). Мягкие
ошибки гораздо дешевле, они мало влияют на производительность приложения (по
сравнению с жесткими ошибками). Мягкие ошибки могут происходить потому, что
совместно используемая страница уже была отображена на другой процесс, либо нужна
просто новая обнуленная страница, либо нужная страница была удалена из рабочего
набора процесса, но запрашивается повторно до того, как ее повторно использовали.
Мягкие ошибки могут возникать также из-за того, что страницы были сжаты для
эффективного увеличения размера физической памяти. Для большинства конфигура-
ций центрального процессора память и ввод-вывод в текущих системах эффективнее
сжимать, вместо того чтобы тратиться на дорогостоящий ввод-вывод (с точки зрения
производительности и энергозатрат), требующий чтения страницы с диска.
11.5. Управление памятью
1013
Когда физическая страница больше не отображается таблицей страниц ни одного из
процессов, она попадает в один из трех списков: свободных, модифицированных или
резервных. Те страницы, которые никогда больше не понадобятся (такие, как страницы
стека завершающегося процесса), освобождаются немедленно. Те страницы, которые
могут снова дать страничную ошибку, попадают либо в список модифицированных,
либо в список резервных (в зависимости от того, был ли бит «измененная» установлен
для какого-либо элемента таблицы страниц, который отображал эту страницу с момен-
та ее последнего считывания с диска). Страницы из модифицированного списка будут
в конечном итоге записаны на диск, а затем перемещены в список резервных.
Диспетчер памяти может выделять страницы по мере необходимости (используя
список либо свободных, либо резервных страниц). Перед размещением страницы
и копированием с диска диспетчер памяти всегда проверяет списки резервных и моди-
фицированных страниц, чтобы проверить, нет ли уже этой страницы в памяти. Схема
опережающей подкачки в Windows преобразует будущие жесткие ошибки в мягкие
(путем чтения страниц, которые могут понадобиться, и помещения их в список ре-
зервных страниц). Диспетчер памяти и сам выполняет небольшой объем опережающей
подкачки — он обращается к группам последовательных страниц (а не к отдельным
страницам). Дополнительные страницы немедленно размещаются в списке резервных
страниц. Это не является расточительством, поскольку издержки диспетчера памяти
гораздо меньше, чем стоимость выполнения операций ввода-вывода. Чтение целого
кластера страниц чуть дороже, чем чтение одной страницы.
Элементы таблицы страниц на рис. 11.17 относятся к номерам физических (а не вир-
туальных) страниц. Для обновления элемента таблицы страниц (и каталога страниц)
ядру нужно использовать виртуальные адреса. Windows отображает таблицы страниц
и каталоги страниц для текущего процесса на виртуальное адресное пространство ядра
при помощи элемента self-map в каталоге страниц (рис. 11.18). Отображая элемент ка-
талога страниц на каталог страниц (карта self-map), мы получаем виртуальные адреса,
которые можно использовать для ссылки на элементы каталога страниц (рис. 11.18, а)
и на элементы таблицы страниц (рис. 11.18, б). Карта self-map занимает 8 Мбайт вир-
туальных адресов ядра для каждого процесса (на процессорах х86). Для простоты на
рисунке показан элемент x86 self-map для 32-разрядных PTE-записей (Page-Table
Entries). На самом деле Windows использует 64-разрядные PTE-записи, поэтому си-
стема может воспользоваться более чем 4 Гбайт физической памяти. С 32-разрядными
PTE-записями элемент self-map использует в каталоге страниц только одну PDE-
запись
(Page-Directory Entry) и поэтому занимает только 4 Мбайт адресов, а не 8 Мбайт.
Алгоритм замещения страниц
Когда количество свободных физических страниц памяти становится небольшим, дис-
петчер памяти начинает готовить физические страницы — он удаляет их из процессов
пользовательского режима и из системных процессов (которые используют страницы
в режиме ядра). Цель — сделать так, чтобы самые важные виртуальные страницы при-
сутствовали в памяти, а остальные находились на диске. Самое главное — определить,
что значит важные. В Windows ответ на этот вопрос дается при помощи концепции
рабочего набора. Каждый процесс (не поток) имеет рабочий набор. Этот набор состоит
из отображенных страниц, которые находятся в памяти и на которые, следовательно,
можно ссылаться без получения страничных ошибок. Размер и состав рабочего набора
меняются на протяжении работы потоков процесса.
1014
Глава 11. Изучение конкретных примеров: Windows 8
Рис. 11.18. Карта self-map в Windows используется для отображения физических страниц:
а — каталога страниц; б — таблиц страниц — на виртуальные адреса ядра (показанные
для 32-разрядных PTE-записей)
Рабочий набор процесса описывается двумя параметрами: минимальным и макси-
мальным размерами. Эти границы не жесткие, поэтому процесс может иметь меньше
страниц в памяти, чем его минимум, или (в некоторых обстоятельствах) больше, чем
его максимум. Все процессы стартуют с одинаковыми минимумом и максимумом, но
эти границы с течением времени могут меняться (либо они могут определяться объ-
ектом задания — для тех процессов, которые содержатся в этом задании). Начальный
минимум по умолчанию находится в диапазоне 20–50 страниц, а начальный макси-
мум по умолчанию — в диапазоне 45–345 страниц (в зависимости от общего объема
физической памяти системы). Однако системный администратор может изменить эти
значения по умолчанию. Вряд ли это будут делать обычные домашние пользователи,
но администраторы серверов могут это сделать.
Рабочие наборы вступают в дело только тогда, когда количество доступной физиче-
ской памяти системы становится низким. В противном случае процессам разрешается
расходовать память по своему усмотрению, при этом максимум рабочего набора часто
значительно превышается. Но когда система попадает в условия дефицита памяти
(memory pressure), диспетчер памяти начинает втискивать процессы обратно в их
рабочие наборы, начиная с тех процессов, которые больше всех превышают свое мак-
симальное значение. Существует три уровня активности диспетчера рабочих наборов,
все они периодические (по таймеру).
1. Доступно большое количество памяти: сканирование страниц со сбросом битов
доступа и использованием их значений для представления возраста каждой стра-
ницы. Оценка неиспользованных страниц в каждом рабочем наборе.
11.5. Управление памятью
1015
2. Памяти становится недостаточно: для всех процессов со значительным процентом
неиспользованных страниц добавление страниц в рабочие наборы прекращается
и начинается замена самых старых страниц (при возникновении потребности
в новой странице). Замененные страницы попадают в списки резервных или мо-
дифицированных.
3. Памяти недостаточно: усечение (то есть уменьшение) рабочих наборов до значе-
ния ниже их максимума (путем удаления самых старых страниц).
Диспетчер рабочих наборов запускается каждую секунду, он вызывается из потока
диспетчера установки баланса
(balance set manager). Диспетчер рабочего набора ре-
гулирует объем выполняемой им работы (чтобы не перегрузить систему). Он также
отслеживает запись страниц (из списка модифицированных) на диск, чтобы быть
уверенным, что список не вырастет до слишком большого размера (при этом он при
необходимости будит поток ModifiedPageWriter).
Управление физической памятью
Ранее мы упомянули три списка физических страниц: список свободных страниц,
список резервных страниц и список модифицированных страниц. Есть и четвертый
список, который содержит обнуленные свободные страницы. Системе часто нужны
обнуленные страницы. Когда процессам даются новые страницы или когда считыва-
ется последняя неполная страница из конца файла, тогда нужна нулевая страница.
Для заполнения страницы нулями требуется время, поэтому лучше создавать нулевые
страницы в фоновом режиме (при помощи потока с низким приоритетом). Есть также
пятый список, используемый для страниц, в которых были обнаружены аппаратные
ошибки (при помощи аппаратных средств обнаружения ошибок).
На все страницы системы есть ссылки в элементах таблиц страниц или в одном из этих
пяти списков, совокупность которых называется базой данных номеров страничных
блоков
(Page Frame Number Database, PFN database). На рис. 11.19 показана структура
этой базы данных. Таблица индексирована по номеру физического страничного блока.
Элементы таблицы имеют фиксированную длину, но для разных типов элементов
(например, совместно используемых либо закрытых) используются разные форматы.
Действительные элементы содержат состояние страницы и счетчик — сколько таблиц
страниц указывают на данную страницу (так что система может определить, когда
страница больше не используется). Страницы рабочих наборов указывают, в каком
элементе на них есть ссылки. Имеется также указатель на таблицу страниц процесса,
который указывает на страницу (для тех страниц, которые совместно не используются)
или на таблицу страниц прототипов (для совместно используемых страниц).
Дополнительно имеется ссылка на следующую страницу списка (если она есть),
а также прочие поля и флаги (такие, как «read in progress» — «идет чтение», «write in
progress» — «идет запись» и т. д.). Для экономии места списки связаны друг с другом
при помощи полей, в которых имеется индекс (а не указатель) следующего элемента.
Элементы таблиц для физических страниц используются также для подсчета битов
«измененная», обнаруженных в элементах разных таблиц страниц, которые указывают
на физическую страницу (из-за совместного использования страниц). Там имеется так-
же информация, которая используется для представления отличий для страниц памяти
больших серверов (имеющих такую память, которая для определенных процессоров
работает быстрее, — это компьютеры с архитектурой NUMA).