Иллюстрированный самоучитель по теории операционных систем
Адресация оперативной памяти
С точки зрения процессора, оперативная память представляет собой массив пронумерованных ячеек. Номер каждой ячейки памяти называется ее адресом. Разрядность адреса является одной из важнейших характеристик процессора и реализуемой им системы команд. Разрядность важна не как самоцель, а потому, что ею обусловлен объем адресуемой памяти – адресного пространства. Системы с 16-разрядным адресом способны адресовать 64 Кбайт (65 536) ячеек памяти, а с 32-разрядным – 4 Гбайт (4 294 967 296) ячеек. В наше время адресуемая память в 4 Гбайт для многих приложений считается неприемлемо маленькой и требуется 64-разрядная адресация.
Процессору обычно приходится совершать арифметические операции над адресами, поэтому разрядность адреса у современных процессоров обычно совпадает с разрядностью основного АЛУ.
У некоторых компьютеров адресация (нумерация) ячеек памяти фиксированная: одна и та же ячейка памяти всегда имеет один и тот же номер. Такая адресация называется физической. Адрес при этом разбит на битовые поля, которые непосредственно используются в качестве номера физической микросхемы памяти, и номеров строки и столбца в этой микросхеме. Напротив, большинство современных процессоров общего назначения используют виртуальную адресацию, когда номер конкретной ячейки памяти определяется не физическим размещением этой ячейки, а контекстом, в котором происходит адресация. Способы реализации виртуальной памяти и необходимость ее применения обсуждаются в Главе 5.
В старых компьютерах размер адресуемой ячейки памяти данных совпадал с разрядностью АЛУ центрального процессора и разрядностью шины данных. Адресуемая ячейка называлась словом. В процессорах манчестерской архитектуры, которые могут использовать одну и ту же память как для команд, так и для данных, оба размера определялись длиной команды. Из-за этого многие процессоры такого типа имели странные по современным представлениям разрядности – 48, 36, иногда даже 25 бит.
БЭСМ-6
Так, БЭСМ-6 имела слово разрядностью 48 бит и команды длиной 24 бита, состоявшие из 15-разрядного адресного поля и 9-разрядного кода операции. Адресное поле позволяло адресовать 32К слов. В одном слове размещалось две команды, при этом команды перехода могли указывать только на первую из упакованных в одно слово команд.
У процессоров гарвардской архитектуры (имеющих раздельные памяти для команд и данных) разрядность АЛУ и размер команды не связаны.
Microchip PIC
Микроконтроллеры семейства PIC фирмы Microchip имеют 8-разрядное АЛУ и накристалльное ОЗУ той же разрядности [www.microchip.com PICMicro]. Команды этих микроконтроллеров размещаются в ПЗУ (также накристалльном), в котором каждое слово имеет 12 бит и содержит одну команду. Аналогично БЭСМ-6, команда микроконтроллера состоит из адресного поля (которое может содержать как адрес, так и константное значение длиной 1 байт) и кода операции. Под код операции остается всего четыре бита, поэтому команд, имеющих полное адресное поле, может быть не более 16. Адресное пространство микроконтроллера составляет 8 бит, т. е. всего 256 слов кода и 256 байт данных. Однако при помощи ухищрения, называемого банковой адресацией (подробнее об этом см. в разд. «Банки памяти»), старшие модели семейства PIC адресуют и по несколько килобайтов как кода, так и данных.
Впрочем, для многих целей и 256 команд вполне достаточно. Самый маленький в мире Web-сервер [www.ccs.cs.umass.edu] реализован именно на основе PIC. В 512 слов кода удалось упаковать реализацию полноценных подмножеств протоколов RS232 (использованная модель микроконтроллера не имеет аппаратно реализованного последовательного порта), РРР, TCP/IP и HTTP. Web-сервер состоит из двух микросхем – собственно сервера и кристалла флэш-памяти, в котором хранятся экспортируемые сервером HTML-документы и изображения. Сервер включается в последовательный порт компьютера и получает питание от этого порта.
Разработчик сервера рекламирует его как основу (или, во всяком случае, как демонстрацию технической возможности) создания Web-интерфейсов для разнообразного бытового оборудования.
Адресация памяти
Содержание
Методы адресации [2]
Адресное пространство
Исполнение программ
Кодирование адресов
Вычисление адресов
Способы адресации
Подразумеваемый операнд
В команде может не содержаться явных указаний об операнде; в этом случае операнд подразумевается и фактически задается кодом операции команды.
Подразумеваемый адрес
В команде может не содержаться явных указаний об адресе участвующего в операции операнда или адреса, по которому должен быть размещен результат операции, но этот адрес подразумевается.
Непосредственная адресация
В команде содержится не адрес операнда, а непосредственно сам операнд. При непосредственной адресации не требуется обращения к памяти для выборки операнда и ячейки памяти для его хранения. Это способствует уменьшению времени выполнения программы и занимаемого ею объёма памяти. Непосредственная адресация удобна для хранения различного рода констант.
Прямая адресация
Адрес указывается непосредственно в виде некоторого значения, все ячейки располагаются на одной странице. Преимущество этого способа в том, что он самый простой, а недостаток — в том, что разрядность регистров общего назначения процессора должна быть не меньше разрядности шины адреса процессора.
Относительная (базовая) адресация
При этом способе адресации исполнительный адрес определяется как сумма адресного кода команды и базового адреса, как правило хранящегося в специальном регистре — регистре базы.
Относительная адресация позволяет при меньшей длине адресного кода команды обеспечить доступ к любой ячейке памяти. Для этого число разрядов в базовом регистре выбирают таким, чтобы можно было адресовать любую ячейку оперативной памяти, а адресный код команды используют для представления лишь сравнительно короткого «смещения». Смещение определяет положение операнда относительно начала массива, задаваемого базовым адресом.
Укороченная адресация
В адресном поле командного слова содержатся только младшие разряды адресуемой ячейки. Дополнительный указательный регистр.
Регистровая адресация
Регистровая адресация является частным случаем укороченной. Применяется, когда промежуточные результаты хранятся в одном из рабочих регистров центрального процессора. Поскольку регистров значительно меньше чем ячеек памяти, то небольшого адресного поля может хватить для адресации.
Косвенная адресация
Адресный код команды в этом случае указывает адрес ячейки памяти, в которой находится адрес операнда или команды. Косвенная адресация широко используется в малых и микроЭВМ, имеющих короткое машинное слово, для преодоления ограничений короткого формата команды (совместно используются регистровая и косвенная адресация).
Адресация слов переменной длины
Эффективность вычислительных систем, предназначенных для обработки данных, повышается, если имеется возможность выполнять операции со словами переменной длины. В этом случае в машине может быть предусмотрена адресация слов переменной длины, которая обычно реализуется путем указания в команде местоположения в памяти начала слова и его длины.
Стековая адресация
Стековая память, реализующая безадресное задание операндов, особенно широко используется в микропроцессорах и Мини-ЭВМ.
Автоинкрементная и автодекрементная адресации
Поскольку регистровая косвенная адресация требует предварительной загрузки регистра косвенным адресом из оперативной памяти, что связано с потерей времени, такой тип адресации особенно эффективен при обработке массива данных, если имеется механизм автоматического приращения или уменьшения содержимого регистра при каждом обращении к нему. Такой механизм называется соответственно автоинкрементной и автодекрементной адресацией. В этом случае достаточно один раз загрузить в регистр адрес первого обрабатываемого элемента массива, а затем при каждом обращении к регистру в нём будет формироваться адрес следующего элемента массива.
При автоинкрементной адресации сначала содержимое регистра используется как адрес операнда, а затем получает приращение, равное числу байт в элементе массива. При автодекрементной адресации сначала содержимое указанного в команде регистра уменьшается на число байт в элементе массива, а затем используется как адрес операнда.
Автоинкрементная и автодекрементная адресации могут рассматриваться как упрощенный вариант индексации — весьма важного механизма преобразования адресных частей команд и организации вычислительных циклов, поэтому их часто называют автоиндексацией.
Индексация
Для реализуемых на ЭВМ методов решения математических задач и обработки данных характерна цикличность вычислительных процессов, когда одни и те же процедуры выполняются над различными операндами, упорядоченно расположенными в памяти. Поскольку операнды, обрабатываемые при повторениях цикла, имеют разные адреса, без использования индексации требовалось бы для каждого повторения составлять свою последовательность команд, отличающихся адресными частями.
Программирование циклов существенно упрощается, если после каждого выполнения цикла обеспечено автоматическое изменение в соответствующих командах их адресных частей согласно расположению в памяти обрабатываемых операндов. Такой процесс называется модификацией команд, и основан на возможности выполнения над кодами команд арифметических и логических операций.
Понятие адреса в оперативной памяти
Все эти действия выполняются автоматически, без участия программиста, то есть механизм виртуальной памяти является прозрачным по отношению к пользователю.
Наиболее распространенными реализациями виртуальной памяти является страничное, сегментное и странично-сегментное распределение памяти, а также свопинг.
Суть концепции виртуальной памяти заключается в том, что адреса, к которым обращается выполняющийся процесс, отделяются от адресов, реально существующих в оперативной памяти.
Главной особенностью виртуальной памяти является преобразование (или трансляция) адреса, к которому производится обращение со стороны программы, в реальный адрес, причём это преобразование должно выполняться быстро. Механизмы динамического преобразования адресов (ДПА) преобразуют смежные адреса виртуальной памяти в необязательно смежные адреса реальной памяти. Таким образом, пользователь освобождается от необходимости учитывать размещение своих процедур и данных в реальной памяти. Программа обращается к виртуальной памяти по виртуальному адресу.
Преимущество ВП состоит в том, что объем ОЗУ не может быть увеличено ни
практически, ни теоретически. (Это попросту невозможно ни какими средствами
нельзя оптимизировать или преобразовать ячейки памяти, для того, чтобы, скажем,
помещать туда два бита информации вместо одного).
В настоящее время все множество реализаций виртуальной памяти может быть представлено тремя классами:
— страничная виртуальная память организует перемещение данных между памятью и диском страницами — частями виртуального адресного пространства фиксированного и сравнительно небольшого размера (достоинства — высокая скорость обмена, низкий уровень фрагментации; недостатки — сложно организовать защиту данных, разделенных на части механически);
— сегментная виртуальная память предусматривает перемещение данных сегментами — частями виртуального адресного пространства произвольного размера, полученными с учетом смыслового значения данных (достоинства — «осмысленность» сегментов упрощает их защиту; недостатки — медленное преобразование адреса, высокий уровень фрагментации);
— сегментно-страничная виртуальная память сочетает достоинства обоих предыдущих подходов.
Национальная библиотека им. Н. Э. Баумана
Bauman National Library
Персональные инструменты
Адресация памяти
Содержание
Типы адресов памяти
Физические адреса
Эффективные адреса
Эффективный адрес — это начало пути вычисления физического адреса. Он задаётся в аргументах индивидуальной машинной инструкции, и вычисляется из значений регистров, смещений и масштабирующих коэффициентов, заданных в ней явно или неявно.
Логические адреса
Линейные адреса
Эффективный адрес — это смещение от начала сегмента — его базы. Если сложить базу и эффективный адрес, то получим число, называемое линейным адресом:
lin_addr = segment.base + eff_addr
Преобразование логический → линейный не всегда может быть успешным, так как при его исполнении проверяется несколько условий на свойства сегмента, записанных в полях его дескриптора. Например, проверяется выход за границы сегмента и права доступа.
Виртуальные адреса
В литературе и в документации других архитектур встречается ещё один термин — виртуальный адрес. Он не используется в документации Intel на IA-32, однако встречается, например, в описании Intel® Itanium, в котором сегментация не используется. Можно смело считать, что для IA-32 виртуальный == линейный. В советской литературе по вычислительной технике этот вид адресов также именовался математическим.
Единица измерения адреса
Некоторые старые компьютеры (десятичные компьютеры) были десятизначными с цифровой адресацией. Например, каждый адрес в магнитной памяти IBM 1620 идентифицировал одну шестиразрядную двоично-кодированную десятичную цифру, состоящую из бита четности, бита флага и четырех числовых битов. В 1620 использовались пятизначные десятичные адреса, поэтому в теории максимально возможный адрес был 99,999. На практике CPU поддерживал 20000 ячеек памяти и мог добавить до двух дополнительных модулей внешней памяти, каждый из которых поддерживает 20 000 адресов, в общей сложности 60 000 (00000-59999).
Размер слова в зависимости от размера адреса
Размер слова является характеристикой для данной архитектуры компьютера. Он обозначает количество цифр, которое процессор может обрабатывать за один раз. Современные процессоры, включая встроенные системы, обычно имеют размер слова 8, 16, 24, 32 или 64 бита; Большинство современных компьютеров общего назначения используют 32 или 64 бита. В истории же использовалось много различных вариантов, включая 8, 9, 10, 12, 18, 24, 36, 39, 40, 48 и 60 бит.
Очень часто, когда речь идет о размере слова современного компьютера, также оценивается размер адресного пространства на этом компьютере. Например, компьютер, называемый «32-битным», также обычно разрешает 32-разрядные адреса памяти; 32-разрядный компьютер с байтовой адресацией может адресовать 2^32 = 4,294,967,296 байт памяти или 4 гибибайта (GB). Это позволяет эффективно хранить адрес памяти одним словом.
Однако это не всегда выполняется. Компьютеры могут иметь адреса памяти, большие или меньшие, чем размер их слова. Так многие 8-разрядные процессоры, например MOS Technology 6502, поддерживают 16-разрядные адреса, а если бы они их не поддерживали, то они были бы ограничены лишь 256 байтами адресной памяти. 16-разрядные процессоры Intel 8088 и Intel 8086 поддерживают 20-разрядную адресацию через сегментацию, что позволяет им получать доступ к 1 Мбайт, а не 64 Кбайт памяти. Все процессоры Intel Pentium, начиная с Pentium Pro, включают в себя расширения физических адресов (PAE [Источник 5] ), которые поддерживают отображение 36-разрядных физических адресов в 32-разрядные виртуальные адреса.
Теоретически современные 64-разрядные компьютеры с байтовой адресацией могут адресовать 2 64 байта, но на практике объем памяти ограничен процессором, контроллером памяти или особенностями печатной платы (например, количеством разъемов физической памяти или количеством паяемой памяти).
Содержание отдельной ячейки памяти
Адресное пространство в программировании приложений
В современной многозадачной среде процессы приложений обычно имеют в своем адресном пространстве (или пространствах) куски памяти следующих типов:
Некоторые части адресного пространства могут вообще не отображаться.
Схемы адресации
Модели памяти
Многие программисты предпочитают адресовать память таким образом, чтобы не было различий между пространством кода и пространством данных, а также физической и виртуальной памятью, другими словами, численно идентичные указатели относятся к точно одному и тому же байту ОЗУ.
Модели памяти в х86 архитектуре
Старые компьютеры x86 использовали сегментированные адреса модели памяти на основе комбинации двух чисел: сегмента памяти и смещения внутри этого сегмента. Некоторые сегменты неявно трактовались как сегменты кода, предназначенные для команд, сегментов стека или обычных сегментов данных. Хотя использование было разным, сегменты не имели какой-либо защиты памяти. В плоской модели памяти все сегменты (сегментные регистры) обычно устанавливаются в ноль, и только смещения являются переменными.
Адреса памяти: физические, виртуальные, логические, линейные, эффективные, гостевые
Мне периодически приходится объяснять разным людям некоторые аспекты архитектуры Intel® IA-32, в том числе замысловатость системы адресации данных в памяти, которая, похоже, реализовала почти все когда-то придуманные идеи. Я решил оформить развёрнутый ответ в этой статье. Надеюсь, что он будет полезен ещё кому-нибудь.
При исполнении машинных инструкций считываются и записываются данные, которые могут находиться в нескольких местах: в регистрах самого процессора, в виде констант, закодированных в инструкции, а также в оперативной памяти. Если данные находятся в памяти, то их положение определяется некоторым числом — адресом. По ряду причин, которые, я надеюсь, станут понятными в процессе чтения этой статьи, исходный адрес, закодированный в инструкции, проходит через несколько преобразований.
На рисунке — сегментация и страничное преобразование адреса, как они выглядели 27 лет назад. Иллюстрация из Intel 80386 Programmers’s Reference Manual 1986 года. Забавно, что в описании рисунка есть аж две опечатки: «80306 Addressing Machanism». В наше время адрес подвергается более сложным преобразованиям, а иллюстрации больше не делают в псевдографике.
Начнём немного с конца — с цели всей цепочки преобразований.
Физический адрес
Эффективный адрес
Эффективный адрес — это начало пути. Он задаётся в аргументах индивидуальной машинной инструкции, и вычисляется из значений регистров, смещений и масштабирующих коэффициентов, заданных в ней явно или неявно.
Например, для инструкции (ассемблер в AT&T-нотации)
addl %eax, 0x11(%ebp, %edx, 8)
эффективный адрес операнда-назначения будет вычислен по формуле:
eff_addr = EBP + EDX * 8 + 0x11
Логический адрес
Здесь обычно у тех, кто столкнулся с этими понятиями впервые, голова начинает идти кругом. Несколько упростить (или усложнить) ситуацию помогает тот факт, что почти всегда выбор селектора (и связанного с ним сегмента) делается исходя из «смысла» доступа. По умолчанию, если в кодировке машинной инструкции не сказано иного, для получения адресов кода используются логические адреса с селектором CS, для данных — с DS, для стека — с SS.
Линейный адрес
Эффективный адрес — это смещение от начала сегмента — его базы. Если сложить базу и эффективный адрес, то получим число, называемое линейным адресом:
lin_addr = segment.base + eff_addr
Преобразование логический → линейный не всегда может быть успешным, так как при его исполнении проверяется несколько условий на свойства сегмента, записанных в полях его дескриптора. Например, проверяется выход за границы сегмента и права доступа.
Сегментация была модной на некотором этапе развития вычислительной техники. В настоящее она почти всюду была заменена другими механизмами, и используется только для специфических задач. Так, в режиме IA-32e (64-битном) только два сегмента могут иметь ненулевую базу. Для остальных четырёх в этом режиме всегда линейный адрес == эффективный.
Что такое виртуальный адрес?
В литературе и в документации других архитектур встречается ещё один термин — виртуальный адрес. Он не используется в документации Intel на IA-32, однако встречается, например, в описании Intel® Itanium, в котором сегментация не используется. Можно смело считать, что для IA-32 виртуальный == линейный.
В советской литературе по вычислительной технике этот вид адресов также именовался математическим.
Страничное преобразование
Однако общая идея всегда одна и та же: линейный адрес разбивается на несколько частей, каждая из которых служит индексом в одной из системных таблиц, хранящихся в памяти. Записи в таблицах — это адреса начала таблицы следующего уровня или, для последнего уровня — искомая информация о физическом адресе страницы в памяти и её свойствах. Самые младшие биты не преобразуются, а используются для адресации внутри найденной страницы. Например, для режима PAE с размером страниц 4 кбайт преобразование выглядит так:
В разных режимах процессора различается число и ёмкость этих таблиц. Преобразование может завершиться неудачей, если очередная таблица не содержит валидных данных, или права доступа, хранящиеся в последней из них, запрещают доступ к странице; например, при записи в регионы, помеченные как «только для чтения», или попытке чтения памяти ядра из непривилегированного процесса.
Гостевой физический
До введения возможностей аппаратной виртуализации в процессорах Intel страничное преобразование было последним в цепочке. Когда же на одной системе работают несколько виртуальных машин, то физические адреса, получаемые в каждой из них, приходится транслировать ещё один раз. Это можно делать программным образом, или же аппаратно, если процессор поддерживает функциональность EPT (англ. Extended Page Table). Адрес, раньше называвшийся физическим, был переименован в гостевой физический для того, чтобы отличать его от настоящего физического. Они связаны с помощью EPT-преобразования. Алгоритм последнего схож с ранее описанным страничным преобразованием: набор связанных таблиц с общим корнем, последний уровень которых определяет, существует ли физическая страница для указанной гостевой физической.
Полная картина
Я попытался собрать все преобразования адреса в одну иллюстрацию. В ней преобразования обозначены стрелками, типы адресов обведены в рамки.
Как уже было сказано выше, каждое из преобразований может вернуть ошибку для адресов, не имеющих представления в следующем по цепочке виде. Устранение подобных проблем — это задача операционных систем и мониторов виртуальных машин, реализующих абстракцию виртуальной памяти.




