Системное программирование в среде Windows
Шрифт:
Далее, в рамках Win32 у каждого процесса имеется собственное виртуальное адресное пространство объемом 4 Гбайт (232 байт). Разумеется, объем виртуального адресного пространства в Win64 гораздо больше. По крайней мере, половину указанного пространства (2-3 Гбайт; расширение до 3 Гбайт должно производиться во время загрузки) Win32 делает доступной для процесса. Оставшаяся часть виртуального адресного пространства выделяется для совместно используемых данных и кода, системного кода, драйверов и так далее.
Хотя детали описанного распределения памяти и заслуживают интереса, здесь они обсуждаться не будут; прикладные программы используют
Обзор методов управления памятью
Обо всех деталях отображения виртуальных адресов на физические адреса (virtual to physical memory mapping), механизмах страничной подкачки (page swapping) и замещения страниц по запросу (demand paging) и прочих моментах заботится ОС. Эти вопросы подробно обсуждаются в документации по ОС, а также в книге Соломона (Solomon) и Руссиновича (Russinovich) Inside Windows2000. Краткое изложение наиболее существенных сведений приводится ниже:
• Система может располагать сравнительно небольшим объемом физической памяти; на практике для всех систем, кроме Windows XP, необходимый минимум составляет 128 Мбайт, однако в типичных случаях доступные объемы физической памяти оказываются намного большими. [21]
• Каждый отдельный процесс — а таких процессов, как пользовательских, так и системных, может выполняться одновременно несколько — имеет собственное виртуальное адресное пространство, объем которого может значительно превосходить объем доступного физического адресного пространства. Например, емкость виртуального адресного пространства объемом 1 Гбайт, относящегося к одному процессу, в восемь раз превышает емкость физической памяти объемом 128 Мбайт, и таких процессов может быть множество.
21
Цены на модули памяти постоянно снижаются, а "типичный" объем доступной памяти увеличивается, поэтому назвать, какой именно объем памяти является типичным, довольно затруднительно. Во время написания данной книги недорогие системы снабжались памятью объемом 128-256 Мбайт. В большинстве случаев такой памяти будет вполне достаточно, но она не является оптимальной для Windows XP. Для систем Windows Server 2003 требуемый объем памяти обычно гораздо больше указанного.
• ОС преобразует виртуальные адреса в физические адреса.
• Для большинства виртуальных страниц в физической памяти места не хватит, поэтому ОС имеет возможность реагировать на страничные ошибки (page faults), возникающие при попытках обращения к страницам, которые отсутствуют в памяти, и загружать данные с жесткого диска — из системного файла подкачки (swap file) или из обычного файла. Будучи прозрачными для программиста, страничные ошибки отрицательно влияют на производительность, поэтому программы должны проектироваться таким образом, чтобы вероятность возникновения подобных ошибок была сведена к минимуму. Более подробное освещение этой темы, рассмотрение которой выходит за рамки данной книги, вы найдете в справочной документации по ОС.
На рис. 5.1 проиллюстрировано расположение уровней API управления памятью Windows поверх диспетчера виртуальной памяти (Virtual Memory Manager, VMM). API виртуальной памяти Windows (VirtualAlloc, VirtualFree, Virtual-Lock, VirtualUnlock и так далее) работает с целыми страницами. API кучи Windows управляет блоками памяти, размер которых определяется пользователем.
Мы не будем останавливаться на топологии адресного пространства виртуальной памяти, поскольку она не имеет непосредственного отношения к API, различна в Windows 9x и Windows NT и в будущем может измениться. Соответствующая информация содержится в документации Microsoft.
Тем не менее, многим программистам хотелось бы знать больше о своей среде разработки. Начните исследование структуры памяти в вашей системе с вызова следующей функции:
Параметром этой функции служит адрес структуры PSYSTEM_INFO, в которой содержится информация относительно размера системной страницы, а также адресах физической памяти, доступных для приложений.
Куча
Windows поддерживает пулы памяти, называемые кучами (heaps). Процесс может иметь несколько куч, которые используются для распределения памяти.
Рис. 5.1. Архитектура системы управления памятью Windows
Во многих случаях одной кучи вполне достаточно, но в силу ряда причин, о которых будет сказано ниже, иногда целесообразно иметь в своем распоряжении несколько куч. Если одной кучи вам хватает, можно обойтись использованием функций управления памятью, предоставляемых библиотекой С (malloc, free, calloc, realloc).
Кучи являются объектами Windows и, следовательно, имеют дескрипторы. Дескриптор кучи используется при распределении памяти. У каждого процесса имеется куча, заданная по умолчанию, которую использует функция malloc и для получения дескриптора которой используется следующая функция:
Возвращаемое значение: дескриптор кучи процесса; в случае неуспешного завершения — NULL.
Заметьте, что для индикации неудачного завершения функции используется возвращаемое значение NULL, а не INVALID_HANDLE_VALUE, как в случае функции CreateFile.
Программа также может создать несколько различных куч. Иногда для размещения в памяти отдельных структур данных оказывается удобным, чтобы для каждой из них была предусмотрена своя куча. Использование независимых куч обеспечивает ряд преимуществ.
• Отсутствие взаимной дискриминации между потоками. Ни один из потоков не сможет получить больше памяти, чем распределено для ее кучи. В частности, так называемая утечка памяти (memory leak), возникающая в тех случаях, когда программа "забывает" своевременно освободить память, занятую элементами данных, необходимости в которых больше нет, будет влиять лишь на один поток процесса. [22]
22
Понятие потоков вводится в главе 7.