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

В MS-DOS реализовано управление памятью без организации вирту­аль­ного адресного пространства, но с распределением блоков переменной длины. Базовые механизмы ОС опираются только на средства реального режима процессоров x86, и лишь для работы с «верхней» памятью используются осо­бенности адресации 286+ и переключение в защищенный/виртуальный режим.

Память в MS-DOS представляется как непрерывный массив, распреде­ля­емый отдельными блоками. Блоки могут начинаться только на границе пара­графа, поэтому для задания блока достаточно его сегментного адреса. Блоки следуют непосредственно друг за другом и составляют связный список. Вся доступная для распределения память должна быть включена в эти блоки, в том числе и свободная. Последний блок в списке соответствует нераспределенному нефрагментированному остатку памяти.

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

байт 0 – опознавательный маркер блока: 5Ah (‘Z’) – для последнего блока списка, 4Dh (‘M’) – для всех остальных;

байты 1..2 – сегментный адрес PSP программы – владельца блока (в MS-DOS адрес PSP играет роль PID – идентификатора загруженной программы);

байты 3..4 – размер блока в параграфах, при отсутствии «зазоров» между блоками в списке это значение является «относительной» ссылкой на следующий блок (размер самого MCB в этом поле не учитывается!);

байты 8..15 – имя программы – владельца блока.

Поля PID и имени владельца для пустых блоков ожидаются пустыми. Для используемых блоков корректность их значений не гарантируется: обычная их интерпретация справедлива в случаях, если блок был выделен стандарт­ным способом обычной прикладной программе. Блоки, выделенные DOS для своих нужд, имеют PID = 0008h и имя «владельца», начинающееся с комбинаций “SD” (data) или “SC” (code). Внутри «системных» блоков памяти могут организо­вы­ваться вложенные списки с аналогичными структурами суб-блоков и суб-MCB. Маркеры суб-MCB могут содержать значения: 'B' – дис­ковые буферы, 'D' – драйвер устройства, 'F' – системная таблица файлов, 'L' – данные логического диска, 'S' – внутренние стеки DOS; 'X' – кэш FCB и так далее (эта информация считается недокументированной).

Зная адрес одного из блоков, можно просканировать все последующие до конца списка. DOS хранит адрес первого блока в специальной структуре или DIB – DOS Info Block (она же List of Lists). Адрес DIB возвращает в регистрах ES:BX недокументированная функция int 21h AH = 52h. Слово по адресу ES:BX‑2 содержит сегментный адрес первого в списке MCB.

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

– наличие маркера MCB;

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

– блок содержит PSP – начинается с команды int 20h.

Так как первой «нормально» загружаемой программой является обычно командный интерпретатор (как правило, COMMAND.COM), то можно также искать в MCB его имя.

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

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

В MS-DOS предусмотрены три основные функции прерывания int 21h:

AH = 48h – выделение блока памяти. На входе: BX – размер блока в параграфах. На выходе: AX – сегментный адрес выделенного блока, BX – макси­мальный доступный размер этого блока.

AH = 49h – освобождение блока. На входе: ES – сегментный адрес блока.

AH = 4Ah – изменение размера ранее выделенного блока. На входе: ES – сегментный адрес блока, BX – новый размер блока в параграфах. На выходе: BX – максимальный доступный размер этого блока.

Все функции при возникновении ошибки устанавливают флаг CF и возвращают ее код в AX.

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

Контрольные вопросы

1. Организация памяти в MS-DOS.

2. Структура MCB блока.

4. Функции для создания, удаления и изменения размера блока.

5. Организация сложных динамических структур данных.

Варианты заданий

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

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

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

3.3.4. Сформировать путем анализа списка MCB и вывести карту памяти, включая размер блоков и их владельцев.

3.3.5. Реализовать выделение и освобождение блоков памяти без обраще­ний к функциям DOS.

3.3.6. Реализовать перераспределение блока памяти; в случае невозмож­ности увеличить размер блока попытаться переместить его на новое место (текущее содержимое блока копируется).

3.3.7. Объединяет функции вариантов 4..6, допол­няется интерактивным интерфейсом, позволяющим выбирать функции (повышенной сложности).

Лабораторная работа №4
Обработчики прерываний

Цели работы:

1) изучить поддержку прерываний и их использование;

2) научиться создавать и использовать собственные обработчики пре­ры­ваний;

3) научиться создавать и отлаживать резидентные программы.

Наши рекомендации