Чтобы обеспечить эффективный контроль использования памяти, ОС должна выполнять следующие функции:
· отображение адресного пространства процесса на конкретные области физической памяти;
· распределение памяти между конкурирующими процессами;
· контроль доступа к адресным пространствам процессов;
· выгрузка процессов (целиком или частично) во внешнюю память, когда в оперативной памяти недостаточно места;
· учет свободной и занятой памяти.
Адресное пространство — это просто диапазон адресов, обозначающих определенное место в памяти. Адресные пространства подразделяются на три разновидности:
· Физическое адресное пространство
· Линейное адресное пространство
· Логическое адресное пространство, известное также как виртуальное адресное пространство
Физические адреса — это реальные, аппаратные адреса, доступные в системе. Если в системе имеется 64 Мб памяти, в ней допустимые физические адреса могут находиться в диапазоне от 0 до 0x3fffffff (в шестнадцатиричном формате). Каждый адрес соответствует одному набору транзисторов в микросхемах SIMM, установленных вами (или изготовителем), и отдельному сочетанию сигналов на адресной шине процессора.
Адрес — символ или группа символов, которые идентифицируют регистр, отдельные части памяти или некоторые другие источники данных либо место назначения информации.
Виды адресов[2]
· Реальный (англ. real address) — адрес местоположения данных в реальной памяти.
· Виртуальный (англ. virtual address) — адрес в виртуальной памяти, при использовании преобразуется в реальный адрес.
· Логический (англ. logical address) — адрес, определяемый программой путём преобразования ключа данных по некоторому алгоритму; адрес в виртуальной памяти.
· Адрес устройства (англ. unit address) — логический адрес, состоящий из номера канала и номера устройства в канале.
· Физический (англ. physical address) — число, идентифицирующее ячейку или область физической памяти; уникальное имя, однозначно определяющее конкретное внешнее устройство.
Вопрос 12
Статическое распределение памяти эффективо, поскольку на управление памятью во время выполнения не тратится ни времени, ни памяти. Однако этот метод несовместим с рекурсивными вызовами подпрограмм, со структурами данных, размер которых зависит от вычисляемой или вводимой информации, и со многими другими желательными возможностями языка. Читатель, однако, не должен упускать из вида важность статического метода распределения памяти - для многих программ вполне достаточно статического распределения. Два широко используемых языка программирования, Фортран и Кобол, сконструированы в расчете исключительно на статическое распределение памяти. [1]
Статическое распределение памяти состоит в назначении адресов для размещения данных в процессе трансляции. Адреса могут затем корректироваться при загрузке программы, но в процессе исполнения объектной программы остаются неизменными. [2]
Статическое распределение памяти целесообразно проводить в два этапа. На первом этапе выделяется секция памяти каждому блоку, а на втором - назначаются адреса переменным внутри блока.
Однакостатическое распределение памяти возможно лишь в тех случаях, когда количество данных, описанных в блоке, не меняется при повторных входах в блок. [4]
Недостаткомстатического распределения памяти является неэкономное использование памяти, а преимуществом - экономия машинного времени при исполнении объектной программы. В случаях, когда данные не удается разместить в оперативной памяти, это преимущество сводится на нет дополнительными затратами времени на обмен с внешней памятью. В таких случаях динамическое распределение памяти может оказаться более выгодным с точки зрения общих затрат машинного времени. [5]
Пристатическом распределении памяти все данные, описанные в блоке, можно расположить в области памяти, выделенной Аля этого блока. Однако на практике массивы обычно размещают ь отдельном поле массивов. Это связано с тем, что массивы иногда приходится выносить во внешнюю память.
Динамическое распределение памяти — способ выделения оперативной памяти компьютера для объектов в программе, при котором выделение памяти под объект осуществляется во время выполнения программы.
При динамическом распределении памяти объекты размещаются в т.н. «куче» (англ. heap): при конструировании объекта указывается размер запрашиваемой под объект памяти, и, в случае успеха, выделенная область памяти, условно говоря, «изымается» из «кучи», становясь недоступной при последующих операциях выделения памяти. Противоположная по смыслу операция — освобождение занятой ранее под какой-либо объект памяти: освобождаемая память, также условно говоря, возвращается в «кучу» и становится доступной при дальнейших операциях выделения памяти.
По мере создания в программе новых объектов, количество доступной памяти уменьшается. Отсюда вытекает необходимость постоянно освобождать ранее выделенную память. В идеальной ситуации программа должна полностью освободить всю память, которая потребовалась для работы. По аналогии с этим, каждая процедура (функция или подпрограмма) должна обеспечить освобождение всей памяти, выделенной в ходе выполнении процедуры. Некорректное распределение памяти приводит к т.н. «утечкам» памяти, когда выделенная память не освобождается. Многократные утечки памяти могут привести к исчерпанию всей оперативной памяти и нарушить работу операционной системы.
Другая проблема — это проблема фрагментации памяти. Выделение памяти происходит блоками — непрерывными фрагментами оперативной памяти (таким образом, каждый блок — это несколько идущих подряд байтов). В какой-то момент, в куче попросту может не оказаться блока подходящего размера и, даже, если свободная память достаточна для размещения объекта, операция выделения памяти окончится неудачей.
Для управления динамическим распределением памяти используется «сборщик мусора» — программный объект, который следит за выделением памяти и обеспечивает её своевременное освобождение. Сборщик мусора также следит за тем, чтобы свободные блоки имели максимальный размер, и, при необходимости, осуществляет дефрагментацию памяти.