Открытая память
Основной ресурс системы, распределением которого занимается ОС – это оперативная память. Поэтому организация памяти оказывает большое влияние на структуру и возможности ОС. В настоящее время сложилась даже более интересная ситуация – переносимая операционная система UNIX, рассчитанная на машины со страничным диспетчером памяти, произвела жесткий отбор, и теперь практически все машины общего назначения, начиная от х86 и заканчивая суперкомпьютерами или, скажем процессором Alpha, имеют именно такую организацию адресного пространства.
Самый простой вариант управления памятью – отсутствие диспетчера памяти и возможность загружать в системе только один процесс. Именно так работают СР/М и RT-ll SJ (Single-Job, однозадачная). В этих системах программы загружаются с фиксированного адреса PROG_START. В СР/М это ОхIOО; в RT-ll – 01000. По адресам от 0 до начала программы находятся векторы прерываний, а в RT-11 – также и стек программы. Операционная система размещается в старших адресах памяти. Адрес SYS_START, с которого она начинается, зависит от количества памяти у машины и от конфигурации ОС (рис. 4.1).
Рис. 4.1. Управление памятью в однопроцессной ОС с открытой памятью
В этом случае управление памятью со стороны системы состоит в том, что загрузчик проверяет, поместится ли загружаемый модуль в пространство от PROG_START до SYS_START. Если объем памяти, который использует программа, не будет меняться во время ее исполнения, то на этом все управление и заканчивается.
Однако программа может использовать динамическое управление памятью, например функцию malloco или что-то в этом роде. В этом случае уже код maiioco должен следить за тем, чтобы не залезть в системные адреса. Как правило, динамическая память начинает размещаться с адреса PROG_END = PROG_START + PROG_SIZE. FROG_SIZE в данном случае обозначает полный размер программы, т. е. размер ее кода, статических данных и области, выделенной под стек.
Функция malloc () поддерживает некоторую структуру данных, следящую за тем, какие блоки памяти из уже выделенных были освобождены. При каждом новом запросе она сначала ищет блок подходящего размера в своей структуре данных и, только когда этот поиск завершится неудачей, просит новый участок памяти у системы. Для этого используется переменная, которая в библиотеке языка С называется brk_addr (рис. 4.2, пример 4.1).
Рис. 4.2. Загруженная программа и brk_addr