ЗАНЯТИЕ 30. Распределение памяти

Существует ряд базовых вопросов управления памятью, ко¬торые в различных ОС решаются по-разному. Например, следует ли назначать каждому процессу одну непрерывную область физиче¬ской памяти или можно выделять память участками? Должны ли сегменты программы, загруженные в память, находиться на одном месте в течение всего периода выполнения процесса или их можно время от времени сдвигать? Что делать, если сегменты программы не помещаются в имеющуюся память? Как сократить затраты ресурсов системы на управление памятью? Имеется и ряд других не менее интересных проблем управления памятью.
Ниже приводится классификация методов распределения памяти, в которой выделено два класса методов – с перемещением сегментов процессов между ОП и ВП (диском) и без перемещения, т.е. без привлечения внешней памяти (рис. 91). Данная классифика¬ция учитывает только основные признаки методов. Для каждого метода может быть использовано несколько различных алгоритмов его реализации.

Рис. 91. Классификация методов распределения памяти

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

Рис. 92. Вари¬анты фиксиро¬ванного рас-пределения памяти

При использовании разделов с одинаковым размером име¬ются две проблемы.

  1. Программа может быть слишком велика для размещения в разделе. В этом случае программист должен разрабатывать программу, использующую оверлеи, чтобы в любой момент времени требовался только один раздел памяти. Когда требу¬ется модуль, отсутствующий в данный момент в ОП, пользо¬вательская программа должна сама его загрузить в раздел па¬мяти программы. Таким образом, в данном случае управление памятью во многом возлагается на программиста.
  2. Использование ОП крайне неэффективно. Любая программа, независимо от ее размера, занимает раздел целиком. При этом могут оставаться неиспользованные участки памяти большого размера. Этот феномен появления неиспользованной памяти называется внутренней фрагментацией (internal fragmentation).
    Бороться с этими трудностями (хотя и не устранить полно¬стью) можно посредством использования разделов разных разме¬ров. В этом случае программа размером до 8 Мбайт может обой¬тись без оверлеев, а разделы малого размера позволяют уменьшить внутреннюю фрагментацию при загрузке небольших программ.
    В том случае, когда разделы имеют одинаковый раздел, размещение процессов тривиально – в любой свободный раздел. Если все разделы заняты процессами, которые не готовы к немед¬ленной работе, любой из них может быть выгружен для освобож¬дения памяти для нового процесса.
    Когда разделы имеют разные размеры, есть два возможных подхода к назначению процессов разделам памяти. Простейший путь состоит в том, чтобы каждый процесс размещался в наимень¬шем разделе, способном вместить данный процесс (в этом случае в задании пользователя указывался размер требуемой памяти). При таком подходе для каждого раздела требуется очередь планиров¬щика, в которой хранятся выгруженные из памяти процессы, пред¬назначенные для данного раздела памяти. Достоинство такого спо¬соба в возможности распределения процессов между разделами ОП так, чтобы минимизировать внутреннюю фрагментацию.
    Недостаток заключается в том, что отдельные очереди для разделов могут привести к неоптимальному распределению памяти системы в целом. Например, если в некоторый момент времени нет ни одного процесса размером от 7 до 12 Мбайт, то раздел размером 12 Мбайт будет пустовать, в то время как он мог бы использоваться меньшими процессами. Поэтому более предпочтительным является использование одной очереди для всех процессов. В момент, когда требуется загрузить процесс в ОП, выбирается наименьший до¬ступный раздел, способный вместить данный процесс.
    В целом можно отметить, что схемы с фиксированными разделами относительно просты, предъявляют минимальные требо¬вания к операционной системе; накладные расходы работы процес¬сора на распределение памяти невелики. Однако у этих схем име¬ются серьезные недостатки.
  3. Количество разделов, определенное в момент генерации си¬стемы, ограничивает количество активных процессов (т.е. уровень мультипрограммирования).
  4. Поскольку размеры разделов устанавливаются заранее во время генерации системы, небольшие задания приводят к не¬эффективному использованию памяти. В средах, где заранее известны потребности в памяти всех задач, применение рас¬смотренной схемы может быть оправдано, но в большинстве случаев эффективность этой технологии крайне низка.
    Для преодоления сложностей, связанных с фиксированным распределением, был разработан альтернативный подход, извест¬ный как динамическое распределение. В свое время этот подход был применен фирмой IBM в операционной системе для мэйн¬фреймов в OS/MVT (мультипрограммирование с переменным чис¬лом задач – Multiprogramming With a Variable number of Tasks). Позже этот же подход к распределению памяти использован в ОС ЕС ЭВМ .
    При динамическом распределении образуется перемененное количество разделов переменной длины. При размещении процесса в основной памяти для него выделяется строго необходимое коли¬чество памяти. В качестве примера рассмотрим использование 64 Мбайт (рис. 93) основной памяти. Изначально вся память пуста, за исключением области, задействованной ОС. Первые три процесса загружаются в память, начиная с адреса, где заканчивается ОС, и используют столько памяти, сколько требуется данному процессу. После этого в конце ОП остается свободный участок памяти, слиш¬ком малый для размещения четвертого процесса. В некоторый мо¬мент времени все процессы в памяти оказываются неактивными, и операционная система выгружает второй процесс, после чего оста¬ется достаточно памяти для загрузки нового, четвертого процесса.
Рис. 93. Вариант использования памяти

Поскольку процесс 4 меньше процесса 2, появляется еще свободный участок памяти. После того как в некоторый момент времени все процессы оказались неактивными, но стал готовым к работе процесс 2, свободного места в памяти для него не находится, а ОС вынуждена выгрузить процесс 1, чтобы освободить необхо¬димое место и разместить процесс 2 в ОП. Как показывает данный пример, этот метод хорошо начинает работу, но плохо продолжает. В конечном счете, он приводит к наличию множества мелких сво¬бодных участков памяти, в которых нет возможности разместить какой-либо новый процесс. Это явление называется внешней фраг¬ментацией (external fragmentation), что отражает тот факт, что сильно фрагментированной становится память, внешняя по отно¬шению ко всем разделам.
Один из методов преодоления внешней фрагментации – уплотнение (compaction) процессов в ОП. Осуществляется это пе¬ремещением всех занятых участков так, чтобы вся свободная па¬мять образовала единую свободную область. В дополнение к функ¬циям, которые ОС выполняет при распределении памяти динамиче¬скими разделами, в данном случае она должна еще время от вре¬мени копировать содержимое разделов из одного места в другое, корректируя таблицы свободных и занятых областей. Эта проце¬дура называется уплотнением или сжатием.
Перечислим функции операционной системы по управле¬нию памятью в этом случае.

  1. Перемещение всех занятых участков в сторону старших или младших адресов при каждом завершении процесса или для вновь создаваемого процесса в случае отсутствия раздела до¬статочного размера.
  2. Коррекция таблиц свободных и занятых областей.
  3. Изменение адресов команд и данных, к которым обращаются процессы при их перемещении в памяти, за счет использова¬ния относительной адресации.
  4. Аппаратная поддержка процесса динамического преобразова¬ния относительных адресов в абсолютные адреса основной памяти.
  5. Защита памяти, выделяемой процессу, от взаимного влияния других процессов.
    Уплотнение может выполняться либо при каждом заверше¬нии процесса, либо только тогда, когда для вновь создаваемого процесса нет свободного раздела достаточного размера. В первом случае требуется меньше вычислительной работы при корректи¬ровке таблиц свободных и занятых областей, а во втором – реже выполняется процедура сжатия.
    Так как программа перемещается по оперативной памяти в ходе своего выполнения, в данном случае невозможно выполнить настройку адресов с помощью перемещающего загрузчика. Здесь более подходящим оказывается динамическое преобразование ад¬ресов. Достоинствами распределения памяти перемещаемыми раз¬делами являются эффективное использование оперативной памяти, исключение внутренней и внешней фрагментации, недостатком – дополнительные накладные расходы ОС.
    При использовании фиксированной схемы распределения процесс всегда будет назначаться одному и тому же разделу памяти после его выгрузки и последующей загрузке в память. Это позво¬ляет применять простейший загрузчик, который замещает при за¬грузке процесса все относительные ссылки абсолютными адресами памяти, определенными на основе базового адреса загруженного процесса.
    Ситуация усложняется, если размеры разделов равны (или неравны) и существует единая очередь процессов, – процесс по ходу работы может занимать разные разделы. Такая же ситуация возможна и при динамическом распределении. В этих случаях рас¬положение команд и данных, к которым обращается процесс, не является фиксированным и изменяется всякий раз при выгрузке, загрузке или перемещении процесса. Для решения этой проблемы в программах используются относительные адреса. Это означает, что все ссылки на память в загружаемом процессе даются относи¬тельно начала этой программы. Таким образом, для корректной ра¬боты программы требуется аппаратный механизм, который бы транслировал относительные адреса в физические в процессе вы-полнения команды, обращающейся к памяти.
    Применяемый обычно способ трансляции показан на рис.94. Когда процесс переходит в состояние выполнения, в специальный регистрпроцесса, называемый базовым, загружается начальный адрес процесса в основной памяти. Кроме того, используется «гра¬ничный» (bounds) регистр, в котором содержится адрес последней ячейки программы. Эти значения заносятся в регистры при загрузке программы в основную память. При выполнении процесса относи¬тельные адреса в командах обрабатываются процессором в два этапа. Сначала к относительному адресу прибавляется значение базового регистра для получения абсолютного адреса. Затем полу¬ченный абсолютный адрес сравнивается со значением в граничном регистре. Если полученный абсолютный адрес принадлежит дан¬ному процессу, команда может быть выполнена. В противном слу¬чае генерируется соответствующее данной ошибке прерывание.
Рис. 94. Преобразование адресов

Оставить комментарий

avatar
  Подписаться  
Уведомление о