Функции управления памятью
Рисунок 3.1. Функции управления памятью
Функция именования производит отображение точки из пространства имен программы в пространство адресов в виртуальной памяти, иными словами - переводит символьные имена, используемые программистом, в виртуальные адреса.
Функция привязки производит отображение точки из пространства виртуальных адресов в пространство реальных адресов, то есть, переводит виртуальные адреса в адреса физических ячеек памяти.
Функция выборки отображает точку из пространства реальных адресов в значение, то есть, выбирает содержимое памяти по заданному адресу.
Функция именования реализуется по большей части обслуживающими программами, мы рассматриваем ее в следующей главе. Функция выборки всегда реализуется аппаратно. В данной главе нас будет интересовать прежде всего функция привязки адресов. Относительно нее конструктором ОС должен быть решен основной вопрос: на каком этапе подготовки/выполнения программы ее выполнять?
Программист может писать программу, сразу привязывая ее к заведомо известным адресам физической памяти, - это называется программированием в абсолютных адресах. Такое программирование выполняется в специфических случаях, например, для программ, записываемых в ПЗУ. Даже в таких случаях программист часто пользуется символическими именами, возлагая задачу перевода имен в физические адреса на транслятор. Полученная таким образом программа называется абсолютной или неперемещаемой. Она может выполняться только, будучи загруженной по определенному адресу оперативной памяти.
Все прикладные программы и подавляющее большинство системных программ являются перемещаемыми. Это значит, что в программе, подготовленной к выполнению (в том образе программы, который хранится на внешней памяти), обращения к памяти настроены на виртуальные адреса, не привязанные пока к адресам реальной памяти.
Выполнение функции привязки адресов может быть перенесено на этап загрузки. Простейшим вариантом такой системы трансляции является тот, в котором виртуальный адрес представляет собой смещение относительно начала программы, а при загрузке программы в память ко всем виртуальным адресам прибавляется начальный адрес области, в которую программа загружена. Другой вариант - виртуальная адресация производится относительно содержимого некоторого базового регистра, в который при загрузке заносится базовый адрес. Программы, подготовленные таким образом, называются перемещаемыми при загрузке - они могут быть загружены в любую область оперативной памяти, но после загрузки должны оставаться на том же месте в памяти.
Наконец, привязка адресов может делаться уже на этапе выполнения программы. Программа (процесс) обращается к памяти только по виртуальным адресам, а перевод виртуального адреса в реальный производится только при обращении по этому адресу. Между двумя обращениями по одному и тому же виртуальному адресу процесс может быть перемещен операционной системой в другую область реальной памяти. Системные средства, ответственные за привязку адресов, будут "знать" о произведенном перемещении и при втором обращении привяжут тот же виртуальный адрес к новому реальному адресу. Поскольку виртуальный адрес не изменился, то перемещение оказалось совершенно прозрачным для процесса, такие процессы называются перемещаемыми динамически. При такой трансляции адресов привязка выполняется при каждом обращении к памяти, то есть, очень часто. Поэтому естественным решением является выполнение этой функции на аппаратном уровне. Аппаратура переводит виртуальные адреса в реальные, используя некоторые таблицы трансляции. Подготовка таблиц трансляции адресов - операция, выполняемая для процесса одноразово, модификация их производится также нечасто (при перемещении процесса), поэтому задача формирования и модификации таблиц трансляции возлагается на ОС.
Отметим, что иногда виртуальной памятью называют именно эти свойства аппаратуры вычислительной системы и вытекающие из них возможности для процессов работать с виртуальным адресным пространством большего размера, чем размер имеющейся в системе реальной памяти. Мы же следуем более широкой интерпретации [13]: виртуальная память это то адресное пространство, в котором разрабатывается процесс. Такое понимание соответствует определению ОС "с точки зрения пользователя", которое мы дали в разделе 1.4. В данном случае ОС скрывает от процесса организацию низкоуровневого ресурса (реальной памяти) и конструирует ресурс более высокого уровня (виртуальная память), более удобный в обращении. Такая интерпретация не принимает во внимание, на каком этапе - загрузки или выполнения - производится трансляция адресов, и имеется ли в системе аппаратная поддержка этой трансляции. В частном случае размер виртуальной памяти может быть и меньше реальной.
Разработка программ, работающих в виртуальном адресном пространстве, имеет целый ряд преимуществ, которые можно сгруппировать по трем основным направлениям.
- Удобство для программиста. Программист имеет в своем распоряжении виртуальную память, представляющую собой адресное пространство либо совершенно плоское - с адресами, линейно возрастающими от 0 до максимального значения, либо сегментированное в соответствии с потребностями задачи. При этом он не заботится о том, как будет размещен его процесс в реальной памяти, ОС может отобразить виртуальную память в реальную даже таким образом, что смежные участки виртуального адресного пространства будут отображаться в несмежные участки реальной памяти. Каждый процесс разрабатывается в собственном адресном пространстве, независимом от пространств других процессов.
- Реорганизация памяти. Системные средства управления памятью могут выбрать такое отображение виртуальной памяти в реальную, которое обеспечит максимально эффективное использование ресурса реальной памяти. В случае, когда обеспечивается динамическая трансляция адресов, реорганизация ресурса реальной памяти может производиться и в ходе выполнения процесса, причем совершенно прозрачно для последнего.
- Защита. Процесс никак не может обратиться за пределы своего виртуального адресного пространства. Если ОС обеспечивает отображение таким образом, что виртуальные пространства двух любых процессов не могут перекрывать друг друга в реальной памяти, то никакой процесс не будет иметь доступа к адресному пространству другого процесса.
При наличии аппаратной поддержки системы виртуальной памяти позволяют работать с виртуальными адресными пространствами, размер которых превышает доступный размер оперативной памяти. Это достигается за счет хранения части программ и данных на внешней (дисковой) памяти и управления миграцией данных между оперативной и внешней памятью. Современные вычислительные системы следуют тенденции вводить кэширование между двумя этими уровнями памяти. В ОС Unix, например, тотальное кэширование обеспечивается самой ОС для любого обмена с дисками, следовательно, работает оно и для данных, перемещаемых при управлении памятью. В вычислительных системах ESA имеется два аппаратных промежуточных уровня памяти: расширенная память, которая включается в пространство реальных адресов, но используется только как буфер обмена и собственная буферная память дискового запоминающего устройства. (Расширенная память, может быть выполнена как на тех же элементах, что и основная оперативная память, так и на специальных - не столь быстродействующих, но дешевых).
Многоуровневая память строится обычно по иерархическому принципу. Это означает, что для каждого следующего уровня время доступа больше, чем для предыдущего: t[i] > t[i-1], и объем больше: V[i] > V[i-1]. Последнее обстоятельство делает возможным дублирование информации на уровнях: если данные имеются на i-ом уровне, то их копии сохраняются и на всех уровнях с большими номерами. Обозначим через h[i] отношение присутствия - вероятность того, что данные, запрошенные на i-ом уровне памяти, уже имеются на этом уровне. Если мы имеем n уровней памяти, то для n-го уровня отношение присутствия равно 1 и среднее время доступа tav[n] совпадает с t[n]. Для всех уровней с меньшими номерами среднее время доступа может быть определено рекурсивно: tav[i] = h[i] * t[i] + ( 1 - h[i] ) * tav[i-1].
На программном уровне мы не можем воздействовать ни на t[i], ни на V[i], которое в значительной степени определяет и h[i]. Но мы можем влиять на величину h[i], выбирая для хранения на уровне с меньшим номерам только те данные, обращение к которым производится наиболее часто.
В общем случае проектирование менеджера памяти в составе ОС требует выбора трех основных стратегий:
- стратегии размещения: какую область реальной памяти выделить процессу? как вести учет свободной/занятой реальной памяти?
- стратегии подкачки: когда размещать процесс (или часть его) в реальной памяти?
- стратегии вытеснения: если реальной памяти не хватает для удовлетворения очередного запроса, то у какого процесса отобрать ранее выделенный ресурс реальной памяти (или часть его)?
Ниже мы рассмотрим способы реализации этих стратегий для различных моделей памяти. Порядок рассмотрения будет соответствовать принципу "от простого к сложному" и в основном отображать также и историческое развитие моделей памяти:
- фиксированные разделы - модель, не использующая аппаратную трансляцию адресов;
- односегментная виртуальная память - развитие фиксированных разделов для аппаратной трансляции адресов.
- модели виртуальной памяти, использующие развитые средства аппаратной трансляции адресов;
- многосегментная;
- страничная;
- комбинированная сегментно-страничная.