Управление памятью

Основные задачи управления памятью. Виртуальные и физические адреса. Организация работы с фиксированными и динамическими разделами. Сегментная и страничная организация памяти, управление ею в различных организационных системах: MS DOS, Windows, Unix.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 29.01.2012
Размер файла 57,3 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

РЕФЕРАТ

УПРАВЛЕНИЕ ПАМЯТЬЮ

Основные задачи управления памятью

Основная память (она же ОЗУ) является важнейшим ресурсом, эффективное использование которого решающим образом влияет на общую производительность системы.

Для однозадачных операционных систем (ОС) управление памятью не является серьезной проблемой, поскольку вся память, не занятая системой под собственные нужды, может быть отдана в распоряжение единственного пользовательского процесса. Процедуры управления памятью решают следующие задачи:

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

обеспечение настройки запускаемой программы на выделенные адреса памяти;

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

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

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

предоставление процессам возможностей получения и освобождения дополнительных областей памяти в ходе работы;

эффективное использование ограниченного объема основной памяти для удовлетворения нужд всех работающих процессов, в том числе с использованием дисков как расширения памяти;

изоляция памяти процессов, исключающая случайное или намеренное несанкционированное обращение одного процесса к областям памяти, занимаемым другим процессом;

предоставление процессам возможности обмена данными через общие области памяти.

Виртуальные и физические адреса

Понятие «адрес памяти» может рассматриваться с двух точек зрения. С одной стороны, при написании любой программы ее автор либо явно указывает, по каким адресам должны размещаться переменные и команды (так бывает при программировании на языке ассемблера), либо присвоение конкретных адресов доверяется системе программирования. Те адреса памяти, которые записаны в программе, принято называть виртуальными адресами.

С другой стороны, каждой ячейке памяти компьютера соответствует ее адрес, который должен помещаться на шину адреса при каждом обращении к ячейке. Эти адреса называются физическими.

В ЭВМ первого поколения не делалось различия между виртуальными и физическими адресами: в программе требовалось указывать физические адреса. Это означало, что такая программа могла правильно работать, только если сама программа и все ее данные при каждом запуске (и на любом компьютере) должны были размещаться по одним и тем же физическим адресам. Такой подход стал крайне неудобным, как только была поставлена задача передать распределение памяти под управление ОС.

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

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

Есть два принципиально разных ответа на этот вопрос.

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

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

Распределение памяти без использования виртуальных адресов

Настройка адресов

Если в программе используются значения физических адресов, то правильность ее работы зависит от того, по каким адресам загружена в память сама программа. Это особенно очевидно для команд перехода: если в программе есть команда «Перейти по адресу 1000», то сдвиг этой программы в памяти приведет к тому, что переход будет выполнен на совсем другую команду, хотя и по тому же адресу.

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

Для решения этой проблемы в составе файла программы приходится хранить словарь перемещений - список всех тех мест в программе, которые содержат адреса, требующие настройки на адрес загрузки программы. Такая настройка в большинстве случаев представляет собой просто сложение адреса загрузки с адресом, хранящимся в файле программы, и выполняется при загрузке программы в память. Выполнение настройки приводит к некоторой задержке при запуске программ.

Более поздние архитектуры ЭВМ позволили в значительной мере упростить дело за счет использования относительной адресации - указания адреса как смещения относительно значения в некотором базовом регистре. Теперь настройка требовалась лишь для нескольких команд, загружающих значения в базовые регистры. Более того, для многих не слишком сложных программ стало возможно обойтись вообще без словаря перемещений (например, если все адреса указаны только как смещения относительно начала программы). Подобные программы, способные без изменений правильно работать при загрузке по любому адресу, называются позиционно-независимыми, в отличие от перемещаемых программ, требующих настройки адресов.

В системе MS-DOS все файлы типа COM содержат позиционно-независимые программы, а файлы EXE - перемещаемые.

Распределение с фиксированными разделами

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

Рис. 1

Возможны два варианта организации работы с фиксированными разделами.

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

В более развитых системах программа хранится в перемещаемом формате, а при ее запуске система выбирает наиболее подходящий по размеру свободный раздел. При отсутствии такового программа ожидает.

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

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

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

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

Распределение с динамическими разделами

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

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

Сегментная организация памяти

Перейдем теперь к рассмотрению способов организации памяти, которые базируются на использовании виртуальных адресов, аппаратно преобразуемых в физические при выполнении команд. Два основных вида организации виртуальной памяти - сегментная и страничная организация.

При сегментной организации вся виртуальная память, используемая программой, разбивается на части, называемые сегментами. Это разбиение выполняется либо самим программистом (если он программирует на языке ассемблера), либо компилятором используемого языка программирования. Размеры сегментов могут быть различными, но в пределах максимального размера, используемого в данной архитектуре. Разбиение обычно производится на логически осмысленные части, такие, как сегмент данных, сегмент кода, сегмент стека и т.п. Большая программа может содержать несколько сегментов одного типа, например, несколько сегментов кода или данных.

Таким образом, при сегментной организации у программы нет единого линейного адресного пространства. Виртуальный адрес состоит из двух частей: селектора сегмента и смещения от начала сегмента.

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

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

При каждом обращении к виртуальному адресу аппаратными средствами выполняется преобразование пары «сегмент : смещение» в физический адрес. Упрощенная схема такого преобразования показана на рис. 2.

Рис. 2

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

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

Но откуда возьмется свободное место в памяти? По всей вероятности, системе придется для этого убрать из памяти какой-то другой сегмент, принадлежащий либо к этому же, либо к иному процессу. Копия вытесняемого сегмента должна остаться в файле подкачки. Чтобы избежать лишней работы, в каждой записи таблицы хранится флаг, отмечающий, является ли сегмент в памяти «чистым» или «грязным», т.е. совпадает ли его содержимое с дисковой копией или же оно было изменено в памяти после последней загрузки с диска. «Грязный» сегмент должен быть сохранен на диске, для «чистого» сохранение не требуется. Если сегмент определен как доступный только для чтения, то он заведомо «чистый».

Для борьбы с фрагментацией можно время от времени производить дефрагментацию, т.е. перемещение всех сегментов, находящихся в памяти, на новые места, без «дырок» в памяти между сегментами. При этом, однако, требуется, чтобы система откорректировала таблицы сегментов всех тех процессов, сегменты которых переместились в физической памяти. Кроме того, перемещение сегментов занимает ощутимое время, поэтому оно недопустимо для сегментов, содержащих, например, обработчики прерываний, которые должны срабатывать очень быстро. Чтобы избежать этих проблем, в некоторых системах сегменты могут находиться в одном из двух состояний:

фиксированный сегмент не должен перемещаться в памяти;

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

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

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

Страничная организация памяти

Эта форма организации виртуальной памяти во многом похожа на сегментную. Основные различия заключаются в том, что все страницы, в отличие от сегментов, имеют одинаковые размеры, а разбиение виртуального адресного пространства процесса на страницы выполняется системой автоматически. Типичный размер страницы - несколько килобайт. Для процессоров Pentium, например, страница равна 4 Кб.

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

Физическая память также считается разбитой на части, размеры которых совпадают с размером виртуальной страницы. Эти части называются физическими страницами или страничными кадрами (page frames). Таблица страниц процесса по структуре похожа на таблицу сегментов. Для каждой виртуальной страницы она содержит режим доступа, флаг присутствия страницы в памяти, номер страничного кадра, флаг чистоты. Если страница отсутствует в памяти, ее данные сохраняются в файле подкачки, который в этом случае чаще называют страничным файлом (page file).

Простейший вариант схемы преобразования виртуального страничного адреса в физический адрес показан на рис. 3.

Рис. 3

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

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

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

Размер пространства виртуальных адресов каждого процесса может быть огромным, ибо он определяется только разрядностью адреса. Для 32-разрядных процессоров этот размер равен 232 = 4 Гб. В настоящее время трудно представить программу, которой может всерьез понадобиться столько памяти, да и компьютер с таким объемом памяти - вещь не рядовая. На самом деле, программа обычно использует лишь небольшую часть своего адресного пространства, не более нескольких десятков или, в крайнем случае, сотен мегабайт. Только эти используемые страницы и должны быть отображены на физическую память. Тем не менее, суммарный объем страниц, используемых всеми процессами в системе, обычно превосходит объем имеющейся физической памяти, поэтому использование страничного файла становится неизбежным.

Управление замещением страниц в физической памяти в современных РС строится по принципу загрузки по требованию (demand paging). Это означает следующее. Когда программа только лишь планирует использование определенной области виртуальной памяти (например, для хранения массива переменных, описанного в программе), соответствующие виртуальные страницы помечаются в таблице страниц как существующие, но находящиеся в данный момент на диске. В некоторых системах при этом за виртуальной страницей действительно закрепляются конкретные блоки в страничном файле, хотя из соображений экономии дисковой памяти это можно сделать позже, когда реально потребуется записать страницу на диск. Выделение страниц физической памяти не выполняется до тех пор, пока программа не обратится к одной из ячеек виртуальной страницы. При этом происходит аппаратное прерывание по отсутствию страницы в памяти. Это прерывание обрабатывает часть ОС, которая называется менеджером памяти. Менеджер должен выполнить следующие действия:

найти свободную физическую страницу;

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

если выбранная страница «грязная», т.е. ее содержимое изменялось после того, как она последний раз была прочитана с диска, то «очистить» страницу, т.е. записать ее в соответствующий блок страничного файла;

на освободившуюся физическую страницу прочитать блок страничного файла, закрепленный за запрошенной виртуальной страницей;

откорректировать таблицу страниц, пометив вытесненную страницу как отсутствующую в физической памяти, а прочитанную - как присутствующую и при этом «чистую»;

повторить обращение к запрошенному виртуальному адресу, теперь уже присутствующему в физической памяти.

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

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

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

Менеджер памяти работает в иной ситуации. Обращения к памяти происходят с огромной частотой, при выполнении почти каждой команды процессора. Абсолютно нереально при каждом обращении предпринимать какие-то программные действия. Из этого следует, что алгоритм выбора вытесняемой страницы должен опираться на аппаратную поддержку. Поскольку алгоритм LRU не так просто реализовать аппаратно, вместо него часто используют алгоритмы, более простые в реализации, пусть даже они менее эффективны.

Недостатком страничной организации является то, что при большом объеме виртуального адресного пространства сама таблица страниц должна быть очень большой. При размере страницы 4 Кб и адресном пространстве 4 Гб таблица должна содержать миллион записей! Однако вряд ли программа процесса постоянно использует весь огромный диапазон адресов. Как правило, на каждом интервале времени интенсивно используются только некоторые части таблицы страниц (это еще одно проявление локальности ссылок). Желательно иметь возможность вытеснять на диск временно неиспользуемые части таблицы страниц. Такая возможность в современных процессорах обеспечивается использованием более сложной, двухуровневой схемы страничной адресации. В этой схеме все адресное пространство делится на разделы равной величины, каждый из которых описывается отдельной небольшой таблицей страниц. Имеется также каталог таблиц страниц, который описывает текущее состояние каждой таблицы точно так же, как сама таблица страниц описывает состояние страниц памяти. Те таблицы страниц, которые долго не используются, вытесняются на диск и соответствующим образом помечаются в каталоге. Виртуальный адрес делится не на две, а на три части. Старшие разряды адреса указывают позицию таблицы в каталоге, средние разряды - позицию страницы в таблице, младшие - смещение адреса от начала страницы.

Сравнение сегментной и страничной организации

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

К преимуществам сегментной организации в литературе обычно относят следующие.

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

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

Гораздо реже называется еще одна, более прозаическая причина использования сегментов, которая на самом деле в определенный период являлась очень веской. Если в используемой архитектуре компьютера разрядность адреса в командах слишком мала (например, 16 разрядов, как у процессоров i286, что позволяет адресовать всего лишь 64 Кб), а размер программы и ее данных достигает многих мегабайт, то единственное решение - использовать много сегментов по 64 Кб.

Для современных процессоров разрядность адреса составляет 32 или даже 64 бита, что снимает необходимость возиться с большим количеством мелких сегментов. При этом на первый план выходят достоинства страничной организации:

программист не должен вообще думать о разбиении программы и ее данных на части ограниченного размера (сегменты), в его распоряжении единое пространство виртуальных адресов;

исключается возможность фрагментации физической памяти и связанные с этим проблемы;

как правило, уменьшается обмен данными с диском, поскольку в него включаются только отдельные страницы, а не целые сегменты.

Для сравнительной оценки сегментной и страничной организации полезно также вспомнить историю развития версий Windows. Версия Windows 2.0 была ориентирована на процессор i286, имевший сегментную организацию памяти с 16-разрядным смещением в сегменте. В эти годы фирмы Intel и Microsoft активно защищали сегментную модель, подчеркивая ее достоинства. Однако в Windows 3.0 были уже частично использованы новые возможности процессора i386, а именно, страничная организация памяти. Поскольку эта версия по-прежнему была основана на 16-разрядных адресах, использование сегментов оставалось необходимым, что привело к сложной сегментно-страничной модели памяти. Зато переход к 32-разрядным версиям Windows NT и Windows XP сопровождался фактическим отказом от использования сегментного механизма в пользу чисто страничной организации памяти. Формально же теперь все адресное пространство пользователя укладывается в один очень большой сегмент размером 4 Гб.

Большим преимуществом использования виртуальной памяти, как в сегментном, так и в страничном варианте, является возможность легко и просто изолировать процессы в памяти. Для этого достаточно, чтобы система не отображала никакие виртуальные страницы двух разных процессов на одну и ту же физическую страницу. Тогда процессы просто «не будут видеть» друг друга в памяти и не смогут повредить друг другу.

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

Управление памятью в MS-DOS

MS-DOS - это ОС, работающая в реальном режиме процессора i86, что предполагает использование адресного пространства размером всего лишь 1 Мб. На самом деле, в компьютерах IBM гарантируется наличие лишь 640 Кб основной памяти, старшие же адреса памяти заняты под BIOS и видеопамять, хотя среди них попадаются разрозненные куски оперативной памяти, называемые UMB (верхний блок памяти).

Адрес в реальном режиме записывается в формате [сегмент : смещение], однако здесь сегмент - это не селектор, адресующий строку таблицы сегментов, просто номер параграфа памяти (1 параграф = 16 байт). Поэтому можно считать, что в MS-DOS используются только физические адреса.

В принципе, программы, работающие в MS-DOS, могут получить доступ к памяти за пределами 1 Мб, но для этого требуется специальный драйвер расширенной памяти.

Поскольку делить имеющуюся память между несколькими процессами не приходится, распределение получается бесхитростное. Основные области памяти показаны на рис. 4.

Рис. 4

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

Для пущей экономии памяти некоторые нерезидентные модули DOS могут занимать верхнюю часть области пользователя, но только до тех пор, пока не будут затерты пользовательской программой, которой потребуется вся имеющаяся память.

Часть системной памяти и вся область пользователя разбита на прилегающие друг к другу блоки, размер которых кратен параграфу. Перед началом каждого блока памяти размещается блок управления памятью (MCB, Memory Control Block), который занимает один параграф и содержит следующие данные:

признак, определяющий, последний ли это блок памяти или за ним будут еще блоки (соответственно буква `Z' или `M', это, видимо, опять Марк Збиковский отметился);

адрес PSP программы, владеющей этим блоком (0 означает свободный блок);

размер блока в параграфах;

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

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

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

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

Почему блок среды выделяется раньше, чем блок PSP?

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

MS-DOS предоставляет в распоряжение пользователя функции, позволяющие выполнять основные действия с блоками памяти.

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

Освобождение ранее выделенного блока.

Изменение размера блока. Уменьшение блока возможно всегда, увеличение - только в том случае, если после данного блока расположен свободный блок достаточного размера.

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

Управление памятью в Windows

Принято считать, что каждый процесс, запущенный в Windows, получает в свое распоряжение виртуальное адресное пространство размером 4 Гб. Это число определяется разрядностью адресов в командах: 232 байт = 4 Гб.

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

Но даже и в этом смысле процессу доступно лишь около 2 Гб младших адресов виртуальной памяти. В частности, для Windows NT старшие 2 Гб с адресами от 8000000016 до FFFFFFFF16 доступны только системе. Такое решение позволило уменьшить время, затрачиваемое при вызове системных функций, поскольку отпадает необходимость изменять при этом отображение страниц, нужно только разрешить их использование. Однако, чтобы сам вызов API-функций был возможен, системные библиотеки, которые содержат эти функции, размещаются в младшей, пользовательской половине виртуального пространства.

В Windows XP принято хулиганское решение: система и здесь располагается в старшей половине памяти, но эта половина доступна процессу пользователя и для чтения, и для записи. При этом вызов системы становится еще проще, но зато система становится беззащитной перед любой некорректной программой, лезущей куда не надо.

Кроме старших 2 Гб, процессу недоступны еще некоторые небольшие области в начале и в конце виртуального пространства. В Windows NT недоступны адреса с 0000000016 по 0000FFFF16 и с 7FFF000016 по 7FFFFFFF16, т.е. два кусочка по 64 Кб. Это сделано с целью выявления такой типичной ошибки программирования, как использование неинициализированных указателей, которые обычно попадают в запретные диапазоны адресов.

Для 64-разрядных процессоров размер виртуального адресного пространства возрастает до трудно представимых 264 байт (17 миллиардов гигабайт, если угодно), однако Windows XP выделяет в распоряжение каждого процесса «всего лишь» 7152 гигабайта с адресами от 0 до 6FBFFFFFFFF16, а остальное адресное пространство может использоваться только системой.

Рассмотрим теперь, каким образом программа процесса может использовать свое адресное пространство.

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

Регион памяти всегда имеет размеры, кратные 4 Кб (т.е. он содержит целое число страниц), а его начальный адрес кратен 64 Кб.

Для выделения региона используется функция VirtualAlloc. Она требует указания следующих параметров.

Начальный виртуальный адрес региона. Если указана константа NULL, то система сама выбирает адрес. Если указан адрес, не кратный 64 К, то система округляет его вниз.

Размер региона. При необходимости система округляет его до величины, кратной 4 Кб.

Тип выделения. Здесь указывается одна из констант MEM_RESERVE (резервирование памяти) или MEM_COMMIT (передача физической памяти), смысл которых будет подробно рассмотрен ниже, или комбинация обеих констант.

Тип доступа. Он определяет, какие операции могут выполняться со страницами выделенной памяти. Наиболее важны следующие типы доступа.

PAGE_READONLY - доступ только для чтения, попытка записи в память приводит к ошибке.

PAGE_READWRITE - доступ для чтения и записи.

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

Самое важное, что следует понять про выделение регионов, это смысл операций резервирования и передачи памяти.

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

Попытка программы обратиться к адресу в зарезервированном, но не переданном регионе приведет к ошибке.

Передача физической памяти (MEM_COMMIT) означает, что за каждой страницей виртуальной памяти региона система закрепляет… нет, вовсе не страницу физической памяти, как можно подумать. Закрепляется блок размером 4 Кб в страничном файле. В таблице страниц процесса переданные страницы помечаются как отсутствующие в памяти.

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

Резервирование и передача памяти могут выполняться одновременно, при одном обращении к функции VirtualAlloc, которой для этого нужно передать комбинацию обеих констант: MEM_RESERVE + MEM_COMMIT. Есть и другой вариант: сначала зарезервировать регион памяти, а затем, по мере необходимости, передавать физическую память либо всему региону сразу, либо его отдельным частям (субрегионам). Для этого в первый раз функция VirtualAlloc вызывается с константой MEM_RESERVE и, как правило, без указания конкретного адреса. Затем вызывается VirtualAlloc с константой MEM_COMMIT и с указанием адреса ранее зарезервированного региона или соответствующего субрегиона.

Все описанное полностью соответствует понятию загрузки страниц по требованию. В качестве особенностей реализации замещения страниц в Windows следует отметить следующее.

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

Процесс может запереть в памяти некоторый диапазон адресов, чтобы воспрепятствовать вытеснению соответствующих страниц на диск. Суммарный размер памяти, запертой одним процессом, по умолчанию не должен превосходить 30 страниц. Длительное удержание одним процессом большого числа страниц запертыми в памяти привело бы к уменьшению объема памяти, доступного для других процессов (да и для незапертых страниц того же процесса).

При запуске нового процесса Windows использует практически тот же механизм выделения регионов памяти, который был описан в предыдущем пункте. Отличие в том, что выделение памяти выполняет сама система. Кроме того, нет необходимости в использовании страничного файла, поскольку для хранения страниц, вытесненных на диск, как нельзя лучше подходит сам EXE-файл (или DLL-файл, содержащий разделяемую библиотеку функций). При запуске программы Windows резервирует достаточное количество виртуальных страниц и закрепляет за ними блоки EXE-файла. При этом нет необходимости выполнять такое действие, как «загрузка» программы в традиционном смысле. Чтение кодов программы выполняется по мере необходимости, согласно общему принципу загрузки страниц по требованию.

Как правило, текст программы не подвергается изменениям в ходе ее выполнения. Это означает, что соответствующие виртуальные страницы остаются «чистыми» и при их вытеснении нет необходимости в записи на диск. Если один и тот же исполняемый файл используется одновременно несколькими процессами (что вполне возможно для EXE-файла в случае запуска нескольких экземпляров программы, а для DLL-файлов является правилом), то на один и тот же файл отображаются виртуальные страницы каждого из этих процессов. При этом вполне возможно, что в таблицах страниц разных процессов один и тот же исполняемый файл будет соответствовать разным диапазонам виртуальных адресов.

Проблема возникает в том случае, если по логике работы программы должна выполняться запись в некоторые страницы памяти, соответствующие исполняемому файлу. Это нормальное явление, поскольку в состав EXE-файла могут входить области памяти, отведенные для статических переменных программы. Очевидно, нельзя позволить программе изменять свой собственный файл только потому, что изменились значения переменных. Тем более, если файл используется сразу в нескольких процессах и в каждом из них переменные принимают разные значения. Выход, используемый Windows NT в этой ситуации, заключается в следующем. Все виртуальные страницы, соответствующие выполняемому файлу, выделяются со специальным атрибутом доступа PAGE_WRITECOPY, т.е. «копирование при записи». Пока процессы только читают данные из этих страниц, все происходит, как описано выше. Если же процесс пытается выполнить запись на страницу с таким атрибутом, то происходит прерывание, которое система обрабатывает следующим образом. В страничном файле выделяется блок, в который копируется содержимое данной страницы из EXE-файла. В таблице страниц помечается, что эта виртуальная страница теперь закреплена не за EXE-файлом, а за блоком, выделенным из страничного файла. После этого операция записи успешно выполняется, а при вытеснении страницы она будет сохранена в страничном файле. Таким образом, страничный файл все-таки используется, но только для тех страниц программы, которые изменяются в ходе работы.

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

Нетрудно понять, что те же средства, которые используются для отображения исполняемого файла на виртуальную память, могут быть применены и к любому другому файлу. В Windows программистам предоставляется возможность создавать и использовать объекты типа «отображение файла» (file mapping).

Работа с таким объектом требует предварительной подготовки. Сначала программа должна создать объект, вызвав функцию CreateFileMapping. Среди параметров этой функции можно отметить:

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

тип доступа к объекту (только для чтения или и для записи);

размер объекта;

имя объекта, которое может использоваться для того, чтобы разные процессы могли работать с одним и тем же объектом «отображение файла».

Функция возвращает хэндл созданного или открытого объекта.

Не втором этапе процесс вызывает функцию MapViewOfFile, передавая ей как параметры хэндл объекта «отображение файла», а также размер участка файла, который должен быть отображен, и смещение начала этого участка от начала файла.

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

На самом деле, конечно, данные из файла еще не находятся в памяти. Просто в таблице страниц отмечено, что за такими-то страницами виртуальной памяти закреплены блоки файла. На сей раз не страничного файла и не EXE-файла программы, а того файла, который использовался при создании объекта «отображение файла». Далее начинает действовать все тот же стандартный механизм загрузки страниц по требованию, т.е. реальное чтение из файла произойдет тогда, когда программа обратится к виртуальным адресам, соответствующим отображенному участку файла.

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

Если два процесса работают с одним и тем же объектом «отображение файла» и участки файла, которые они отображают в свою память, хотя бы частично пересекаются, то Windows гарантирует, что любые изменения данных, сделанные на этом участке одним процессом, сейчас же становятся доступными другому процессу. Таким образом, два процесса фактически работают с общей областью памяти, как показано на рис. 5.

Рис. 5

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

Самое забавное, что файл-то здесь и не обязателен. Если при создании объекта «отображение файла» в качестве хэндла файла указано специальное значение FFFFFFFF16, то Windows связывает страницы памяти с блоками страничного файла. В этом случае объект может использоваться только как средство обмена данными между процессами, без привязки к конкретному файлу. При закрытии объекта «отображение файла» его данные в этом случае не сохраняются.

Управление памятью в UNIX

управление память адрес операционная система

Дать общую характеристику управления памятью в UNIX затруднительно, поскольку эта часть системы претерпела наибольшие изменения за долгий период существования UNIX, пройдя путь от управления динамическими разделами физической памяти до современной схемы замещения страниц по требованию, подобной той, которая используется в Windows.

Каждый процесс в UNIX имеет собственное виртуальное адресное пространство, разделяющееся на области программы, данных и стека. В зависимости от архитектуры памяти компьютера, область памяти UNIX может быть реализована как один или несколько сегментов памяти, как набор виртуальных страниц или просто как область в физической памяти. Адреса и размеры областей хранятся как часть контекста процесса.

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

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

Ядро системы имеет собственные области памяти. При выполнении системных вызовов ядро работает в контексте вызвавшего процесса, т.е. оно имеет доступ как к собственной памяти, так и к областям памяти процесса.

Эффективное использование ограниченного объема физической памяти обеспечивается работой системных процессов-«демонов», управляющих перемещением информации между памятью и файлом подкачки. В ранних реализациях UNIX, не использовавших механизм виртуальных страниц, была возможна только подкачка и вытеснение целых процессов. Демон подкачки (системный процесс с идентификатором 0) периодически отслеживал состояние процессов и принимал решение о вытеснении отдельных процессов на диск и подкачке в освободившуюся память одного из ранее вытесненных процессов. При этом во внимание принималась длительность пребывания процесса в памяти или на диске, текущее состояние процесса (спящие процессы - более подходящие кандидаты на вытеснение, чем готовые) и его размер (часто таскать туда-сюда большие процессы невыгодно).

В современных реализациях, основанных на страничной организации памяти, значительную роль играет понятие списка свободных страниц, которые могут быть немедленно выделены, если какой-либо процесс обратится к виртуальной странице, отсутствующей в памяти. В этот список заносятся страницы, к которым долго не было обращения со стороны процессов. Поскольку в отношении страниц памяти трудно реализовать алгоритм LRU, обычно используется более простой алгоритм «второго шанса» (его другое название - «алгоритм часов»). Идея заключается в следующем. Для каждой физической страницы в таблице страниц хранятся бит использования и бит модификации. Эти биты устанавливаются аппаратно: бит использования - при каждом обращении к странице, а бит модификации - при записи на страницу. Системный процесс, называемый демоном замещения страниц, активизируется периодически (по таймеру) и следит, не слишком ли мал размер списка свободных страниц. Обычно порог устанавливается равным ? общего объема физической памяти. Если число свободных страниц ниже этого порога, демон начинает циклически проверять все физические страницы. Если у страницы установлен бит использования, то этот бит сбрасывается. Если же бит уже был сброшен, то страница включается в список свободных. Таким образом, страница попадает в список свободных, если после последнего обращения к ней страничный демон успел дважды ее опросить. Если у страницы установлен бит модификации (в другой терминологии, если страница «грязная»), то перед ее зачислением в список свободных система сохраняет данные в страничном файле. Зачисление в список свободных страниц не означает немедленной потери данных, и если процесс успеет обратиться к странице до того, как она будет отдана другому процессу, эта страница будет исключена из числа свободных.

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

Здесь описан (весьма приблизительно) лишь один из вариантов управления памятью, реализованных в различных версиях UNIX и в Linux. Поскольку алгоритмы управления физической памятью являются «внутренним делом» системы и не регламентируются никакими стандартами, соответствующие алгоритмы, используемые в разных версиях системы, могут значительно отличаться.


Подобные документы

  • Организация памяти компьютера и простые схемы управления ею. Принципы связывания адресов. Динамическое распределение и свопинг. Сегментная и сегментно-страничная организация памяти. Выталкивание редко используемой страницы. Описание работы с программой.

    курсовая работа [3,1 M], добавлен 19.01.2016

  • Как осуществляется трансляция адресов при страничной организации. Что такое компактировка и как с ее помощью избавиться от внешней фрагментации. Что такое регистр таблицы страниц, сегментация. Методы распределения памяти в виде отдельных сегментов.

    контрольная работа [236,2 K], добавлен 23.12.2016

  • Распределение памяти фиксированными и динамическими, а также перемещаемыми разделами, особенности данного процесса в Windows. Функция VirtualAlloc: переданная и зарезервированная память. Выделение памяти функцией malloc, методика и анализ результатов.

    контрольная работа [225,5 K], добавлен 01.12.2013

  • Распределение виртуальной памяти. Страничная и сегментная организации виртуальной памяти. Сегментно-страничная организация виртуальной памяти. Преобразование виртуального адреса в физический. Упрощение адресации памяти клиентским программным обеспечением.

    курсовая работа [440,7 K], добавлен 04.03.2014

  • Архитектура компьютеров и возможности операционной системы по управлению памятью. Суть концепции виртуальной памяти. Аппаратно-независимые и аппаратно-зависимые средства управления виртуальной памятью. Сегментно-страничная организации виртуальной памяти.

    презентация [355,2 K], добавлен 27.12.2010

  • Улучшение параметров модулей памяти. Функционирование и взаимодействие операционной системы с оперативной памятью. Анализ основных типов, параметров оперативной памяти. Программная часть с обработкой выполнения команд и размещением в оперативной памяти.

    курсовая работа [99,5 K], добавлен 02.12.2009

  • Распределение оперативной памяти фиксированными, динамическими и перемещаемыми разделами. Распределение с использованием внешней памяти. Принципы рaботы матричного принтера. Проектирование символов и разработка программы, реализующей их вывод на печать.

    курсовая работа [241,3 K], добавлен 01.07.2011

  • Основные классификации операционных систем. Операционные системы семейства OS/2, UNIX, Linux и Windows. Разграничение прав доступа и многопользовательский режим работы. Пользовательский интерфейс и сетевые операции. Управление оперативной памятью.

    реферат [22,8 K], добавлен 11.05.2011

  • История создания, назначение ОС UNIX. Функциональные характеристики: управление процессами, памятью и файлами, коммуникационные средства и программный интерфейс. Особенности архитектуры ОС UNIX. Способы управления процессами и условия эксплуатации.

    контрольная работа [20,6 K], добавлен 21.02.2009

  • Виртуальные файловые системы. Интерфейс системных вызовов для различных типов файловых систем. Реализация директорий. Индексируемое размещение. Управление свободной памятью. Список свободной дисковой памяти. Различные методы размещения кэша для диска.

    презентация [1,9 M], добавлен 24.01.2014

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.