Типы адресов

Для идентификации переменных и команд используются символьные имена (метки), виртуальные адреса и физические адреса.

Символьные имена присваивает пользователь при написании программы на алгоритмическом языке или ассемблере.

Виртуальные адреса вырабатывает транслятор, переводящий программу на машинный язык. Так как во время трансляции в общем случае не известно, в какое место оперативной памяти будет загружена программа, то транслятор присваивает переменным и командам виртуальные (условные) адреса, обычно считая по умолчанию, что программа будет размещена, начиная с нулевого адреса. Совокупность виртуальных адресов процесса называется виртуальным адресным пространством. Каждый процесс имеет собственное виртуальное адресное пространство. Максимальный размер виртуального адресного пространства ограничивается разрядностью адреса, присущей данной архитектуре компьютера, и, как правило, не совпадает с объемом физической памяти, имеющимся в компьютере.

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

 

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

 

В некоторых случаях (обычно в специализированных системах), когда заранее точно известно, в какой области оперативной памяти будет выполняться программа, транслятор выдает исполняемый код сразу в физических адресах.

 

Тема 2.6. Управление виртуальной памятью

 

Виртуальная машина (ВМ, от англ. virtual machine) —

· программная и/или аппаратная система, эмулирующая аппаратное обеспечение некоторой платформы (target — целевая, или гостевая платформа) и исполняющая программы для target-платформы на host-платформе (host — хост-платформа, платформа-хозяин)

· или виртуализирующая некоторую платформу и создающая на ней среды, изолирующие друг от друга программы и даже операционные системы (см.: песочница);

· также, спецификация некоторой вычислительной среды (например: «виртуальная машина языка программирования Си»).

Виртуальная машина исполняет некоторый машинно-независимый код (например, байт-код, шитый код, p-код) или машинный код реального процессора. Помимо процессора, ВМ может эмулировать работу как отдельных компонентов аппаратного обеспечения, так и целого реального компьютера (включая BIOS, оперативную память, жёсткий диск и другие периферийные устройства). В последнем случае в ВМ, как и на реальный компьютер, можно устанавливать операционные системы (например, Windows можно запускать в виртуальной машине под Linux или наоборот). На одном компьютере может функционировать несколько виртуальных машин (это может использоваться для имитации нескольких серверов на одном реальном сервере с целью оптимизации использования ресурсов сервера).

Концепция виртуальной машины как совокупности ресурсов, которые эмулируют поведение реальной машины, появилась в Кембридже в конце 1960-х годов как расширение концепции виртуальной памяти манчестерской вычислительной машины Atlas (англ.).[1] В целом вычислительный процесс определяется в рамках этой концепции содержимым того рабочего пространства памяти, к которому он имеет доступ. При условии, что конкретная ситуация в этом рабочем пространстве соответствует ожидаемой, процесс не имеет никаких средств для определения того, является ли представленный ему ресурс действительно физическим ресурсом этого типа, или же он имитируется действиями других ресурсов, которые приводят к аналогичным изменениям содержимого рабочего пространства процесса.

Например, процесс не может определить, монопольно ли он использует процессор или же в режиме мультипрограммирования вместе с другими процессами. В виртуальной машине ни один процесс не может монопольно использовать никакой ресурс, и все системные ресурсы считаются ресурсами потенциально совместного использования. Кроме того, использование виртуальных машин обеспечивает развязку между несколькими пользователями, работающими в одной вычислительной системе, обеспечивая определённый уровень защиты данных.

Идея виртуальной машины лежит в основе целого ряда операционных систем, в частности, IBM VM/CMS (и её советского клона СВМ) и DEC VAX/VMS.

Виртуальные машины могут использоваться для:

· защиты информации и ограничения возможностей программ (см.: песочница);

· исследования производительности ПО или новой компьютерной архитектуры;

· эмуляции различных архитектур (например, эмулятор игровой приставки);

· оптимизации использования ресурсов мейнфреймов и прочих мощных компьютеров (см., например: IBM eServer);

· вредоносного кода для управления инфицированной системой: вирус PMBS, обнаруженный в 1993 году, а также руткит SubVirt, созданный в 2006 году в Microsoft Research, создавали виртуальную систему, которой ограничивался пользователь и все защитные программы (антивирусы и прочие).[2]

· моделирования информационных систем с клиент-серверной архитектурой на одной ЭВМ (эмуляция компьютерной сети с помощью нескольких виртуальных машин).

· упрощения управления кластерами — виртуальные машины могут просто мигрировать с одной физической машины на другую во время работы.

· Тестирования и отладки системного программного обеспечения;

Составной частью ядра операционной системы является VMM. Приложения не могут получить к VMM прямой доступ, поэтому для управления памятью им предоставляются различные программные интерфейсы (API).

Интерфейсы:

Virtual Memory API - набор функций, позволяющих приложению работать с виртуальным адресным пространством. Приложение может назначать физические страницы блоку адресов и освобождать их, а также устанавливать атрибуты защиты (см. врезку "Virtual Memory API");

Memory Mapped File API - набор функций использования файлов, отображаемых в память. Этот новый с точки зрения классического устройства ОС механизм предоставляется Win32 API для работы с файлами и взаимодействия процессов между собой;

Heap Memory API - набор функций для управления динамически распределяемыми областями памяти (кучами). Интерфейс построен с помощью Virtual Memory API;

Local, Global Memory API - программный интерфейс для работы с памятью, совместимый с 16-разрядной Windows (лучше его не использовать);

CRT Memory API - функции стандартной библиотеки времени исполнения языка Cи (C Run Time library).

Файлы, отображаемые в память, - это один из самых замечательных сервисов, которые Win32 предоставляет программисту. Его существование стирает для программиста грань между оперативной и дисковой памятью. Действительно, с точки зрения классической теории кэш, оперативная память и дисковое пространство - это три вида памяти, отличающиеся скоростью доступа и размером. Но если заботу о перемещении данных между кэшем и оперативной памятью берут на себя процессор и операционная система, то перемещение данных между оперативной памятью и диском обычно выполняет прикладной процесс с использованием функций read() и write(). Win32 действует иначе: операционная система берет на себя заботу о перемещении страниц адресного пространства процесса, находящихся в файле подкачки, причем в качестве файла подкачки может быть использован любой файл. Иначе говоря, страницы виртуальной памяти любого процесса могут быть помечены как выгруженные, а в качестве места, куда они выгружены, может быть указан файл. Теперь при обращении к такой странице VMM произведет ее загрузку, используя стандартный механизм свопинга. Это позволяет работать с произвольным файлом как с регионом памяти. Данный механизм имеет в Win32 три применения:

  • для запуска исполняемых файлов (EXE) и динамически связываемых библиотек (DLL);
  • для работы с файлами;
  • для совместного использования одной области данных двумя процессами.

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

Рассмотрим механизм запуска программы на выполнение более подробно. При исполнении функции CreateProcess система обращается к VMM для выполнения следующих действий:

  1. Создать адресное пространство процесса.
  2. Зарезервировать в адресном пространстве процесса регион размером, достаточным для размещения исполняемого файла. Начальный адрес региона берется из заголовка EXE-модуля. Обычно он равен 0x00400000, но может быть изменен при построении файла заданием параметра /BASE компоновщика.
  3. Отобразить исполняемый файл на зарезервированное адресное пространство. Тем самым VMM распределяет физические страницы не из файла подкачки, а непосредственно из EXE-модуля.
  4. Отобразить в адресное пространство процесса необходимые ему динамически связываемые библиотеки. Информация о необходимых библиотеках читается из заголовка EXE-модуля. Желательное расположение региона адресов описано внутри отображаемых библиотек. Visual C++, например, по умолчанию устанавливает для своей библиотеки адрес 0x10000000. Этот адрес может тоже изменяться параметром /BASE компоновщика. Если при загрузке выясняется, что данный регион занят, то система попытается переместить библиотеку в другой регион адресов, согласуя это действие с настроечной информацией, содержащейся в DLL-модуле. Однако эта операция снижает эффективность системы, и кроме того, если при компоновке библиотеки настроечная информация удалена (параметр/FIXED), то загрузка становится вообще невозможной. Интересно, что все стандартные библиотеки Windows имеют фиксированный адрес загрузки, и каждая свой собственный.

При одновременном запуске нескольких приложений Win32 отображает один и тот же исполняемый файл и библиотеки на адресные пространства различных процессов. При этом возникает проблема независимого использования процессами статических переменных и областей данных. Кроме того, изменение данных исполняющейся программой не должно приводить к изменению EXE-файла. А ведь он является файлом подкачки и, значит, вытесняемые страницы должны попадать именно в него.

Мы уже обсуждали выше, что Win32, используя технологию lazy evaluation, откладывает решение этой проблемы на максимально возможный срок. Все страницы адресного пространства процесса, на которые отображен EXE-файл, получают атрибут защиты PAGE_WRITECOPY. При попытке записи в такую страницу возникает исключение нарушения защиты, и VMM копирует страницу для обратившегося процесса. В дальнейшем эта страница всегда будет выгружаться в файл подкачки. После копирования происходит повторный старт команды, вызвавшей исключение.

Отображение файла данных в адресное пространство процесса предоставляет мощный механизм работы с файлами - программа может работать с файлом, как с массивом ячеек памяти. Само проецирование файла в память выполняется в три этапа:

  1. Создается объект ядра "файл". В более ранней терминологии это называлось операцией открытия файла. Для создания объекта "файл" используется функция CreateFile(), аналогичная функции open() из CRT-библиотеки.
  2. С помощью функции CreateFileMapping() создается объект ядра "отображаемый файл". При этом используется дескриптор файла (handle), возвращенный функцией CreateFile(). Теперь файл готов к отображению.
  3. Функцией MapViewOfFile() производится отображение объекта "отображаемый файл" или его части в адресное пространство процесса.

Для открепления файла от адресного пространства процесса используется функция UnmapViewOfFile(), а для уничтожения объектов "файл" и "отображаемый файл" - функция CloseHandle.

Общая методика работы с отображаемыми файлами такова:

HANDLE hFile, hFileMapping;

PVOID pMassive;

hFile = CreateFile( оFile Nameп, ... );

hFileMapping = CreateFileMapping( hFile, ... );

CloseHandle( hFile ) ;

pMassive = MapViewOfFile( hFileMapping, ... );

 

/* Здесь производится работа с массивом

pMassive */

 

UnmapViewOfFile( pMassive );

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

Общая область данных может быть создана не только путем проецирования файла, но и путем проецирования части файла подкачки. Для этого в функцию CreateFileMapping() необходимо передать в качестве параметра не дескриптор ранее открытого файла, а константу 1. В этом случае необходимо задать размеры выделяемой области. Кроме того, в параметре lpName можно задать имя глобального объекта в системе. Если это имя задается в системе впервые, то процессу выделяется новая область данных, а если имя было уже задано, то именованная область данных предоставляется для совместного использования.

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

Кучи (heaps) - это динамически распределяемые области данных. При порождении процесса ему предоставляется куча размером 1 Мбайт по умолчанию. Ее размер может изменяться параметром /HEAP при построении исполняемого модуля. Функции библиотеки времени исполнения компилятора (malloc(), free() и т. д.) используют возможности куч.

Для работы с кучей предназначены следующие функции:

HANDLE GetProcessHeap( VOID ) - для получения дескриптора кучи по умолчанию;

LPVOID HeapAlloc( HANDLE hHeap, DWORD dwFlags, DWORD dwSize ) - выделяющая блок памяти заданного размера из кучи и возвращающая указатель на этот блок;

LPVOID HeapReAlloc( HANDLE hHeap, DWORD dwFlags, LPVOID lpOldBlock, DWORD dwSize) - изменяющая размер выделенного блока памяти, при этом она может перемещать блок, если нет достаточного места для простого расширения;

BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem ) - освобождает выделенный блок памяти кучи.

Иногда имеет смысл пользоваться дополнительными кучами, создание которых производится функцией HANDLE HeapCreate(DWORD dwFlags, DWORD dwInitialSize, DWORD dwMaximumSize). Целесообразно использовать дополнительные кучи для защиты друг от друга различных структур данных, для повышения эффективности управления памятью и др. В системах со страничной организацией отсутствует проблема фрагментации физической памяти, однако существует проблема фрагментации адресного пространства. В 4-Гбайт адресном пространстве эта проблема не актуальна, но она имеет значение в куче размером 1 Мбайт. Если элементы какой-либо структуры имеют один размер, а элементы другой структуры - другой, то полезно размещать эти структуры в разных кучах. Кроме того, дополнительные кучи могут быть применены и для уменьшения рабочего множества процесса. В соответствии с принципом локальности работа с разными структурами чаще всего происходит не одновременно. Границы элементов разных структур не выравниваются на границу страницы, поэтому обращение к элементам одной структуры вызывает подкачку всей страницы, а значит, и элементов другой структуры. Это увеличивает рабочее множество процесса.

Можно с уверенностью утверждать, что Windows NT является ничуть не менее "классической" операционной системой в том смысле, что она доставляет примеры удачной реализации во всех разделах теории. Это не удивительно, ведь инженеры, создававшие Windows NT, были очень хорошо знакомы с такими системами, как Unix и Open VMS. При создании Windows NT было найдено много интереснейших технических решений, ряд из которых рассмотрен в данной статье, и название NT - New Technologies - можно считать вполне оправданным.

 








Дата добавления: 2015-07-14; просмотров: 1131;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.013 сек.