Открытая память (продолжение)

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

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

В этой связи нельзя не упомянуть о поучительной истории, связанной с управ­лением памятью в системах линии IBM System 360. В этих машинах не была аппаратных средств управления памятью, и все программы разделяли общее виртуальное адресное пространство, совпадающее с физическим. Адресные ссылки в программе задавались 12-битовым смещением относительно базов го регистра. В качестве базового регистра мог использоваться, в принципе, любой из 16 32-битовых регистров общего назначения. Предполагалось, что пользовательские программы не модифицируют базовый регистр, поэтому можно загружать их с различных адресов, просто перенастраивая значение этого регистра. Таким образом, была реализована одновременная загрузка многих программ в многозадачной системе OS/360.

Однако после загрузки программу уже нельзя было перемещать по памяти: пример, при вызове подпрограммы адрес возврата сохраняется в виде абсолютного 24-битового адреса (в System 360 под адрес отводилось 32-разрядное слово, но использовались только 24 младших бита адреса. В System 370 адрес стал 31-разрядным) и при возврате базовый регистр не применяется. Аналогично, базовый регистр не используется при ссылках на блоки парамет­ров и сами параметры подпрограмм языка FORTRAN (в этом языке все пара­метры передаются по ссылке), при работе с указателями в PL/I и т. д. Переме­щение программы, даже с перенастройкой базового регистра, нарушило бы все такие ссылки.

Разработчики фирмы IBM вскоре осознали пользу перемещения программ по­сле их загрузки и попытались как-то решить эту проблему. Очень любопытный документ "Preparing to Rollin-Rollout Guideline" (Руководство по подготовке [программы] к вкатыванию и выкатыванию; к сожалению, автору не удалось найти полного текста этого документа) описывает действия, которые програм­ма должна была бы предпринять после перемещения. Фактически программа должна была найти в своем сегменте данных все абсолютные адреса и сама перенастроить их.

Естественно, никто из разработчиков компиляторов и прикладного программно­го обеспечения не собирался следовать этому руководству. В результате, про­блема перемещения программ в OS/360 не была решена вплоть до появления машин System 370 со страничным или странично-сегментным диспетчером па­мяти и ОС MVS.

В данном случае проблема фрагментации особенно остра, так как типичный образ процесса занимает значительную часть всего доступного ОЗУ. Если при выделении небольших блоков мы еще можем рассчитывать на "закон больших чисел" и прочие статистические закономерности, то самый про­стой сценарий загрузки трех процессов различного размера может привести нас к неразрешимой ситуации.

Разделы памяти (см. разд. 3.2) отчасти позволяют решить проблему внешней Фрагментации, устанавливая, что процесс должен либо использовать раздел Целиком, либо не использовать его вовсе. Как и все ограничения на размер единицы выделения памяти, это решение загоняет проблему внутрь, переводя внешнюю фрагментацию во внутреннюю. Поэтому некоторые системы предлагают другие способы наложения ограничения на порядок загрузки и выгрузки задач.