Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Архитектура управления памятью



Каждый процесс Win32 имеет собственное виртуальное адресное пространство размером 4Гбайт (232 байт). Win32 делает доступной процессу по меньшей мере его половину (2Гбайт). Остальная часть виртуального адресного пространства предназначена для совместно используемых данных и кода, системного кода, драйверов и т.п.

Обзор управления памятью.

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

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

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

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

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

На рис. 6.1 показан механизм управления памятью в API Win32, основанный на диспетчере виртуальной память (Virtual Memory Manager). API виртуальной памяти Win32 (функции VirtualAlloc, VirtualFree, VirtualLock, VirtualUnlock и т.д. работает с целыми страницами. API “кучи” Win32 может работать с единицами память, определяемыми пользователем.

Функция VitualAlloc распределяет ряда страниц в виртуальном адресном пространстве, а функция VitualAllocEx распределяет ряд страниц в виртуальном адресном пространстве указанного процесса.

LPVOID VitualAlloc (LPVOID lpvAddress, DWORD dwSize,

DWORD dwAllocationType, DWORD dwProtect).

LPVOID VitualAllocEx (HANDLE hProcess, LPVOID lpvAddress,

DWORD dwSize, DWORD dwAllocationType, DWORD dwProtect).

Функция VirtualFree освобождает ряд страниц в виртуальном адресном пространстве. А функция VirtualFreeEx освобождает ряд страниц в виртуальном адресном пространстве указанного процесса.

BOOL VirtualFree(LPVOID lpvAddress, DWORD dwSize, DWORD dwFreeType)

BOOL VirtualFreeEx(HANDLE hProcess, LPVOID lpvAddress, DWORD dwSize,

DWORD dwFreeType)

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

BOOL VirtualLock(LPVOID lpvAddress, DWORD dwSize),

BOOL VirtualUnlock(LPVOID lpvAddress, DWORD dwSize)

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

BOOL VirtualProtect(LPVOID lpvAddress, DWORD dwSize, DWORD dwNewProtect,

DWORD pdwOldProtect)

BOOL VirtualProtectEx(HANDLE hProcess, LPVOID lpvAddress, DWORD dwSize, DWORD dwNewProtect, DWORD pdwOldProtect) [kgl].

Основная литература: [1] – 132 –134 c., [9] – 340 –372 c.

Контрольные вопросы:

1. Механизм управления памятью в API Win32.

2. Основные API функции работы с виртуальной памятью.

3. Что понимается под страничными ошибками?

[gl] Лекция 7. Тема: Динамически распределяемая память [:]

Кучи

Win32 поддерживает области памяти в виде куч (heaps). Процесс может содержать несколько куч, и из них разработчик выделяет память.

Часто достаточно одной кучи, но по приведенным ниже причинам используется и много куч. Если достаточно одной кучи, просто используйте функции библиотеки С для управления памятью (malloc, free, calloc, realloc).

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

HANDLE GetProcessHeap (VOID) Возвращаемое значение: дескриптор кучи процесса; NULL в случае неудачи.

Заметим, что в данном случае для указания на ошибку возвращается значение NULL, а не INVALID_HANDLE_VALUE, как в функции CreateFile.

Программа также может создавать особые кучи. Это относится к тем случаям, ко­гда необходимы отдельные кучи для резервирования отдельных структур данных. Ни­же описаны преимущества отдельных куч.

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

• Многопоточное быстродействие. Благодаря предоставлению каждому потоку от­дельной кучи соревнование между потоками сокращается, что может сущест­венно повысить быстродействие.

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

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

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

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

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

HANDLE HeapCreate (DWORD flOptions,

SIZE_T dwInitialSize, SIZE_T dwMaximumSize);

Возвращаемое значение: дескриптор кучи или NULL в случае ошибки.

Два поля размера имеют тип size_t, а не dword. Тип size_t определен таким образом, что может быть 32-разрядным или 64-разрядным беззнаковым целым, в за­висимости от флагов компилятора (_WIN32 или _WIN64). Тип size_t был введен для обеспечения возможности перехода к WIN64.

Переменная flOptions является комбинацией двух флагов.

• HEAP_GENERATE_EXCEPTIONS— при этом значении неудачные попытки выде­ления памяти вызывают исключения, которые будут обработаны структурным обработчиком исключений (Structured Exception Handler — SEH,). Функция HeapCreate сама по себе не вызывает исключений; если этот флаг ус­тановлен, исключение вызывают при неудаче такие функции, как HeapAlloc.

• HEAP_NO_SERIALIZE — установка этого флага в некоторых случаях позволяет по­лучить небольшое повышение быстродействия. Следует сказать также несколько слов о dwMaximumSize.

• Если значение dwMaximumSize. не равно нулю, виртуальное адресное простран­ство выделяется и в том случае, когда весь указанный объем выделить невоз­можно. Это максимальный размер кучи, которая называется невозрастающей. Данная опция ограничивает размер кучи, возможно, для достижения справедли­вости распределения ресурсов, о которой упоминалось ранее.

• С другой стороны, если значение dwMaximumSize. — нуль, то куча является воз­растающей за пределы начального размера. Эта граница определяется доступ­ным виртуальным адресным пространством, часть которого может быть предос­тавлена другим кучам, и пространством файла подкачки.

Отметим, что кучи не имеют атрибутов безопасности, так как они недоступны из­вне процесса.

Для уничтожения всей кучи используйте функцию HeapDestroy. Это другое ис­ключение из общего правила о том, что функция CloseHandle применяется для уда­ления всех ненужных дескрипторов.

BOOL HeapDestroy (HANDLE hHeap);

Переменная hHeap должна указывать на кучу, созданную функцией HeapCreate. Будьте осторожны, не уничтожьте кучу процесса (полученную функцией GetProcessHeap). Уничтожение кучи освобождает пространство виртуальной памяти и физическую память в файле подкачки. Разумеется, грамотно спроектированные про­граммы должны освобождать кучи, которые больше не используются.

Уничтожение кучи — это также быстрый способ освободить структуру данных без необходимости уничтожать каждый элемент отдельно, хотя экземпляры объектов С++ таким образом не будут уничтожены, поскольку их деструкторы не вызываются. Уничтожение кучи имеет ряд преимуществ.

1. Нет необходимости писать код для поэлементного обхода структуры.

2. Нет необходимости освобождать каждый отдельный элемент.

3. Система не тратит время на поддержку кучи с того момента, когда все структу­ры данных освобождаются одним системным вызовом.





Дата публикования: 2015-11-01; Прочитано: 759 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.01 с)...