Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Рихтер Дж., Назар К. - Windows via C C++. Программирование на языке Visual C++ - 2009

.pdf
Скачиваний:
6263
Добавлен:
13.08.2013
Размер:
31.38 Mб
Скачать

440 Часть III. Управление памятью

Физическая память и страничный файл

В старых операционных системах физической памятью считалась вся оперативная память (RAM), установленная в компьютере. Иначе говоря, если в вашей машине было 16 Мб оперативной памяти, вы могли загружать и выполнять приложения, использующие вплоть до 16 Мб памяти. Современные операционные системы умеют имитировать память за счет дискового пространства. При этом на диске создается страничный файл (paging file), который и содержит виртуальную память, доступную всем процессам.

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

С точки зрения прикладной программы, страничный файл просто увеличивает объем памяти, которой она может пользоваться. Если в вашей машине установлено 1 Гб оперативной памяти, а размер страничного файла на жестком диске составляет также 1 Гб, приложение считает, что объем оперативной памяти равен 2 Гб.

Конечно, 2 Гб оперативной памяти у вас на самом деле нет. Операционная система в тесной координации с процессором сбрасывает содержимое части оперативной памяти в страничный файл и по мере необходимости подгружает его порции обратно в память. Если такого файла нет, система просто считает, что приложениям доступен меньший объем памяти, — вот и все. Но, поскольку страничный файл явным образом увеличивает объем памяти, доступный приложениям, его применение весьма желательно. Это позволяет приложениям работать с большими наборами данных.

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

Теперь посмотрим, что происходит, когда поток пытается получить доступ к блоку данных в адресном пространстве своего процесса. А произойти может одно из двух (рис. 13-2).

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

Во втором сценарии данные, к которым обращается поток, отсутствуют в оперативной памяти, но размещены где-то в страничном файле. Попытка доступа к данным генерирует ошибку страницы (page fault), и процессор таким образом уведомляет операционную систему об этой попытке. Тогда операционная система начинает искать свободную страницу в оперативной памяти;

Глава 13. Архитектура памяти в Windows.docx 441

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

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

Рис. 13-2. Трансляция виртуального адреса на физический

442 Часть III. Управление памятью

Физическая память в страничном файле не хранится

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

Однако система действует не так, иначе на загрузку и подготовку программы к запуску уходило бы слишком много времени. На самом деле происходит вот что: при запуске приложения система открывает его исполняемый файл и определяет объем кода и данных. Затем резервирует регион адресного пространства и помечает, что физическая память, связанная с этим регионом, — сам ЕХЕ-файл. Да-да, правильно: вместо выделения какого-то пространства из страничного файла система использует истинное содержимое, или образ (image) ЕХЕ-файла как зарезервированный регион адресного пространства программы. Благодаря этому приложение загружается очень быстро, а размер страничного файла удается заметно уменьшить.

Образ исполняемого файла (т. е. EXEили DLL-файл), размещенный на жестком диске и применяемый как физическая память для того или иного региона адресного пространства, называется проецируемым в память файлом (memorymapped file). При загрузке EXE или DLL система автоматически резервирует регион адресного пространства и проецирует на него образ файла. Помимо этого, система позволяет (с помощью набора функций) проецировать на регион адресного пространства еще и файлы данных. (О проецируемых в память файлах мы поговорим в главе 17.)

Примечание. Windows может использовать несколько страничных файлов, и, если они расположены на разных физических дисках, операционная система работает гораздо быстрее, поскольку способна вести запись одновременно на нескольких дисках. Чтобы добавить или удалить страничный файл, откройте в Control Panel аплет System, щелкните ссылку Advanced, Adjust The Appearance And Performance Of Windows. На вкладке Advanced

щелкните в секции Virtual Memory кнопку Change. На экране появится следующее диалоговое окно:

Глава 13. Архитектура памяти в Windows.docx 443

Примечание. Когда EXEили DLL-файл загружается с дискеты, Windows 98 и Windows 2000 целиком копируют его в оперативную память, а в страничном файле выделяют такое пространство, чтобы в нем мог уместиться образ загружаемого файла. Если нагрузка на оперативную память в системе невелика, EXEили DLL-файл всегда запускается непосредственно из оперативной памяти.

Так сделано для корректной работы программ установки. Обычно программа установки запускается с первой дискеты, потом поочередно вставляются следующие диски, на которых собственно и содержится устанавливаемое приложение. Если системе понадобится какой-то фрагмент кода EXEили DLL-модуля программы установки, на текущей дискете его, конечно же, нет. Но, поскольку система скопировала файл в оперативную память (и предусмотрела для него место в страничном файле), у нее не возникнет проблем с доступом к нужной части кода программы установки.

Система не копирует в оперативную память образы файлов, хранящихся на других съемных носителях (CD-ROM или сетевых дисках), если только требуемый файл не скомпонован с использованием ключа /SWAPRUN:CD или

/SWAPRUN:NET.

Атрибуты защиты

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

444 Часть III. Управление памятью

Табл. 13-3. Атрибуты защиты страниц памяти

Атрибут защиты

Описание

PAGE_NOACCESS

Попытки чтения, записи или исполнения содержимого памяти на

 

этой странице вызывают нарушение доступа

PAGE_READONLY

Попытки записи или исполнения содержимого памяти на этой

 

странице вызывают нарушение доступа

PAGE_READWRITE

Попытки исполнения содержимого памяти на этой странице вы-

 

зывают нарушение доступа

PAGE_EXECUTE

Попытки чтения или записи на этой странице вызывают наруше-

 

ние доступа

PAGE_EXECUTE_READ

Попытки записи на этой странице вызывают нарушение доступа

PAGE_EXECUTE_

На этой странице возможны любые операции

READWRITE

 

PAGE_WRITECOPY

Попытки исполнения содержимого памяти на этой странице вы-

 

зывают нарушение доступа; попытка записи приводит к тому, что

 

процессу предоставляется «личная» копия данной страницы

PAGE_EXECUTE_

На этой странице возможны любые операции; попытка записи

WRITECOPY

приводит к тому, что процессу предоставляется «личная» копия

 

данной страницы

Некоторые вредоносные программы записывают код в области памяти, предназначенные для хранения данных (например, в стек потока), а затем исполняют его. Для защиты от подобных атак предназначен механизм Windows, названный Data Execution Prevention (DEP). Если DEP включен, система назначает атрибуты PAGE_EXECUTE_* только тем регионам памяти, в которых хранится предназначенный для исполнения код. Остальные атрибуты (чаще всего PAGE_READWRITE) назначаются регионам, предназначенных для хранения данных (например, регионам, занятым кучами и стеками потоков). При попытке исполнения кода, хранящегося в странице, не имеющей атрибута защиты PAGE_EXECUTE_*, процессор генерирует исключение «нарушение доступа».

У механизма структурной обработки исключений Windows (см. главы 23-25) защита еще надежнее. При компоновке приложения с ключом /SAFESEH обработчики исключений регистрируются в специальной таблице, хранящейся в файле образа. При вызове обработчика исключений система проверяет, зарегистрирован ли он в таблице, и разрешает исполнение только зарегистрированных обработчиков.

Подробнее о DEP cм. в официальной статье «03_CIF_Memory_Protection. DOC» по ссылке http://go.microsoft.com/fwlink/?LinkId=28022.

Глава 13. Архитектура памяти в Windows.docx 445

Защита типа «копирование при записи»

Атрибуты защиты, перечисленные и предыдущей таблице, достаточно понятны,

кроме двух последних: PAGE_WRITECOPY и PAGE_EXECUTE_ WRITECOPY.

Они предназначены специально для экономного расходования оперативной памяти и места в страничном файле. Windows поддерживает механизм, позволяющий двум и более процессам разделять один и тот же блок памяти. Например, если вы запустите 10 экземпляров программы Notepad, все экземпляры будут совместно использовать одни и те же страницы с кодом и данными этой программы. И обычно никаких проблем не возникает — пока процессы ничего не записывают в общие блоки памяти. Только представьте, что творилось бы в системе, если потоки из разных процессов начали бы одновременно записывать в один и тот же блок памяти!

Чтобы предотвратить этот хаос, операционная система присваивает общему блоку памяти атрибут защиты «копирование при записи» (copy-on-write). Когда

.exe- или .dll-модуль, проецируется в адресное пространство процесса, система подсчитывает число страниц, доступных для записи (хранящие код страницы обычно помечаются атрибутом PAGE_EXECUTE_READ, а страницы, хранящие данные — атрибутом PAGE_READWRITE) и выделяет в страничном файле место для соответствующего числа страниц. Однако это место реально используется, только если в эти страницы будет что-то записано.

Когда поток в одном процессе попытается что-нибудь записать в общий блок памяти, в дело тут же вступит система и проделает следующие операции:

1.Найдет свободную страницу в оперативной памяти. Заметьте, что при первом проецировании модуля на адресное пространство процесса эта страница будет скопирована на одну из страниц, выделенных в страничном файле. Поскольку система выделяет нужное пространство в страничном файле еще при первом проецировании модуля, сбои на этом этапе маловероятны.

2.Скопирует страницу с данными, которые поток пытается записать в общий блок памяти, на свободную страницу оперативной памяти, полученную на этапе 1. Последней присваивается атрибут защиты PAGE_READWRITE ИЛИ PAGE_EXECUTE_READWRITE. Атрибут защиты и содержимое исходной страницы не меняются.

3.Отобразит виртуальный адрес этой страницы в процессе на новую страницу в оперативной памяти.

Когда система выполнит эти операции, процесс получит свою копию нужной

страницы памяти. Подробнее о совместном использовании памяти и о защите типа «копирование при записи» я расскажу в главе 17.

Кроме того, при резервировании адресного пространства или передаче физической памяти через VirtualAlloc нельзя указывать атрибуты PAGE_WRITECOPY или PAGE_EXECUTE_WRITECOPY. Иначе вызов VirtualAlloc даст ошибку, a

GetLastError вернет код ERROR_INVALID_PARAMETER.

446 Часть III. Управление памятью

Дело в том, что эти два атрибута используются операционной системой, только когда она проецирует образы EXEили DLL-файлов.

Специальные флаги атрибутов защиты

Кроме рассмотренных атрибутов защиты, существует три флага атрибутов защи-

ты: PAGE_NOCACHE, PAGE_WRITECOMBINE и PAGE_GUARD. Они комби-

нируются с любыми атрибутами защиты (кроме PAGE_NOACCESS) побитовой операцией OR.

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

Флаг PAGE_WRITECOMBINE тоже предназначен для разработчиков драйверов устройств. Он позволяет объединять несколько операций записи на устройство в один пакет, что увеличивает скорость передачи данных.

Флаг PAGE_GUARD позволяет приложениям получать уведомление (через механизм исключений) в тот момент, когда на страницу записывается какойнибудь байт. Windows использует этот флаг при создании стека потока. Подробнее на эту тему см. раздел «Стек потока» в главе 16.

Подводя итоги

А теперь попробуем осмыслить понятия адресных пространств, разделов, регионов, блоков и страниц как единое целое. Лучше всего начать с изучения карты виртуальной памяти, на которой изображены все регионы адресного пространства в пределах одного процесса. В качестве примера мы воспользуемся программой VMMap из главы 14. Чтобы в полной мере разобраться в адресном пространстве процесса, рассмотрим его в том виде, в каком оно формируется при запуске VMMap (см. главу 14) под управлением Windows на 32-разрядной процессорной платформе x86. Образец карты адресного пространства VMMap показан в таблице

13-4.

Табл. 13-2. Образец карты адресного пространства процесса в Windows 2000 на 32-разрядном процессоре типа x86

Базовый

Тип

Размер

Блоки

Атрибут(ы)

Описание

адрес

защиты

 

 

 

 

00000000

Free

65536

 

 

 

00010000

Mapped

65536

1

-RW-

 

00020000

Private

4096

1

-RW-

 

00021000

Free

61440

 

 

 

00030000

Private

1048576

3

-RW-

Стек потока

00130000

Mapped

16384

1

-R-

 

Глава 13. Архитектура памяти в Windows.docx 447

Табл. 13-2. (продолжение)

Базовый

Тип

Размер

Блоки

Атрибут(ы)

Описание

адрес

защиты

 

 

 

 

 

00134000 "

Free

49152

 

 

 

 

00140000

Mapped

12288

1

 

-R-

 

00143000

Free

53248

 

 

 

 

00150000

Mapped

819200

4

 

-R-

 

00218000

Free

32768

 

 

 

 

00220000

Mapped

1060864

1

 

-R-

 

00323000

Free

53248

 

 

 

 

00330000

Private

4096

1

 

-RW-

 

00331000

Free

61440

 

 

 

 

00340000

Mapped

20480

1

 

-RWC

\Device\

 

 

 

 

 

 

HarddiskVolume1\

 

 

 

 

 

 

Windows\System32\

 

 

 

 

 

 

en-US\user32.dll.mui

00345000

Free

45056

 

 

 

 

00350000

Mapped

8192

1

 

-R-

 

00352000

Free

57344

 

 

 

 

00360000

Mapped

4096

1

 

-RW-

 

00361000

Free

61440

 

 

 

 

00370000

Mapped

8192

1

 

-R-

 

00372000

Free

450560

 

 

 

 

003E0000

Private

65536

2

 

-RW-

 

003F0000

Free

65536

 

 

 

 

00400000

Image

126976

7

 

ERWC

C:\Apps\14 VMMap.exe

0041F000

Free

4096

 

 

 

 

00420000

Mapped

720896

1

 

-R-

 

004D0000

Free

458752

 

 

 

 

00540000

Private

65536

2

 

-RW-

 

00550000

Free

196608

 

 

 

 

00580000

Private

65536

2

~"

-RW-

 

00590000

Free

196608

 

 

 

 

005C0000

Private

65536

2

 

-RW-

 

005D0000

Free

262144

 

 

 

 

00610000

Private

1048576

2

 

-RW-

 

00710000

Mapped

3661824

1

 

-R-

\Device\

 

 

 

 

 

 

HarddiskVolume1\

 

 

 

 

 

 

Windows\System32\

 

 

 

 

 

 

locale.nls

00A8E000

Free

8192

 

 

 

 

448 Часть III. Управление памятью

Табл. 13-2. (продолжение)

Базовый

Тип

Размер

Блоки

Атрибут(ы)

Описание

адрес

защиты

 

 

 

 

00A90000

Mapped

3145728

2

-R--

 

00D90000

Mapped

3661824

1

-R--

\Device\

 

 

 

 

 

HarddiskVolume1\

 

 

 

 

 

Windows\System32\

 

 

 

 

 

locale.nls

0110E000

Free

8192

 

 

 

01110000

Private

1048576

2

-RW-

 

01210000

Private

524288

2

-RW-

 

01290000

Free

65536

 

 

 

012A0000

Private

262144

2

-RW-

 

012E0000

Free

1179648

 

 

 

01400000

Mapped

2097152

1

-R--

 

01600000

Mapped

4194304

1

-R--

 

01A00000

Free

1900544

 

 

 

01BD0000

Private

65536

2

-RW-

 

01BE0000

Mapped

4194304

1

-R--

 

01FE0000

Free

235012096

 

 

 

739B0000

Image

634880

9

ERWC

C:\Windows\WinSxS\

 

 

 

 

 

x86_microsoft.vc80.

 

 

 

 

 

crt_lfc8b3b9alel8e3b_

 

 

 

 

 

8.0.50727.312_none_

 

 

 

 

 

10b2ee7b9bffc2c7\

 

 

 

 

 

MSVCR80.dll

73A4B000

Free

24072192

 

 

 

75140000

Image

1654784

7

ERWC

C:\Windows\

 

 

 

 

 

WinSxS\x86_

 

 

 

 

 

microsoft.windows.

 

 

 

 

 

common-controls_

 

 

 

 

 

6595b64144ccfldf_

 

 

 

 

 

6.0.6000.16386_none_

 

 

 

 

 

5d07289e07eldl00\

 

 

 

 

 

comctl32.dll

752D4000

Free

1490944

 

 

 

75440000

Image

258048

5

ERWC

C:\Wlndows\

 

 

 

 

 

system32\uxtheme.dll

7547F000

Free

15208448

 

 

 

76300000

Image

28672

1

ERWC

C:\Windows\

 

 

 

 

system32\PSAPI.dll

 

 

 

 

 

76307000

Free

626688

 

 

 

763A0000

Image

512000

7

ERWC

C:\Wmdows\

 

 

 

 

 

system32\USP10.dll

7641D000

Free

12288

 

 

 

Глава 13. Архитектура памяти в Windows.docx 449

Табл. 13-2. (продолжение)

Базовый

Тип

Размер

Блоки

Атрибут(ы)

Описание

адрес

защиты

 

 

 

 

76420000

Image

307200

1

ERWC

C:\Windows\

 

 

 

 

 

system32\GDI32.dll

7646B000

Free

20480

 

 

 

76470000

Image

36864

4

ERWC

C:\Windows\

 

 

 

 

 

system32\LPK.dll

76479000

Free

552960

 

 

 

76500000

Image

348160

4

ERWC

C:\Windows\system32\

 

 

 

 

 

SHLWAPI.dll

76555000

Free

1880064

 

 

 

76720000

Image

696320

7

ERWC

C:\Windows\

 

 

 

 

 

system32\msvcrt.dll

767CA000

Free

24576

 

 

 

767D0000

Image

122880

4

ERWC

C:\Windows\

 

 

 

 

 

system32\IMM32.dll

767EE000

Free

8192

 

 

 

767F0000

 

647168

5

ERWC

C:\Windows\

 

 

 

 

 

system32\USER32.dll

7688E000

Free

8192

 

 

 

76890000

Image

815104

4

ERWC

C:\Windows\

 

 

 

 

 

system32\MSCTF.dll

76957000

Free

36864

 

 

 

76960000

Image

573440

4

ERWC

C:\Windows\system32\

 

 

 

 

 

OLEAUT32.dll

769EC000

Free

868352

 

 

 

76AC0000

Image

798720

4

ERWC

C:\Windows\

 

 

 

 

 

system32\RPCRT4.dll

76B83000

Free

2215936

 

 

 

76DA0000

Image

884736

5

ERWC

C:\Windows\

 

 

 

 

 

system32\kernel32.dll

76E7S000

Free

32768

 

 

 

76E80000

Image

1327104

5

ERWC

C:\Windows\

 

 

 

 

 

system32\ole32.dll

76FC4000

Free

11649024

 

 

 

77AE0000

Image

1171456

9

ERWC

C:\Windows\

 

 

 

 

 

system3Antdll,dH

77BFE000

Free

8192

 

 

 

77C00000

Image

782336

7

ERWC

C:\Windows\system32\

 

 

 

 

 

ADVAPI32.dll

77CBF000

Free

128126976

 

 

 

7F6F0000

Mapped

1048576

2

-R--

 

7F7F0000

Free

8126464

 

 

 

Соседние файлы в предмете Программирование на C++