В однопрограммных операционных системах

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

- область, занимаемая операционной системой;

- область, в которой размещается исполняемая задача; - незанятая ничем (свободная) область памяти.

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

Простое непрерывное распределение и распределение с перекрытием____________ 77

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

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

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

Если есть необходимость создать программу, логическое адресное пространство которой должно быть больше, чем свободная область памяти, или даже больше, чем весь возможный объем оперативной памяти, то используется распределение с перекрытием — так называемые оверлейные структуры (от overlay — перекры­тие, расположение поверх чего-то). Этот метод распределения предполагает, что вся программа может быть разбита на части — сегменты. Каждая оверлейная про­грамма имеет одну главную (main) часть и несколько сегментов (segments), при­чем в памяти машины одновременно могут находиться только ее главная часть и один или несколько не перекрывающихся сегментов.

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

78______________________ Глава 3. Управление памятью в операционных системах

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

Первоначально программисты сами должны были включать в тексты своих про­грамм соответствующие обращения к операционной системе (их называют сис­темными вызовами) и тщательно планировать, какие сегменты могут находиться в оперативной памяти одновременно, чтобы их адресные пространства не пересе­кались. Однако с некоторых пор такого рода обращения к операционной системе системы программирования стали подставлять в код программы сами, автомати­чески, если в том возникает необходимость. Так, в известной и популярной в неда­леком прошлом системе программирования Turbo Pascal программист просто указывал, что данный модуль является оверлейным. И при обращении к нему из основной программы модуль загружался в память и получал управление. Все адреса определялись системой программирования автоматически, обращения к DOS для загрузки оверлеев тоже генерировались системой Turbo Pascal.

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