Адресное пространство процесса
- 4 ГБ на x32 и 16 экзобайт на x64
- делится на следующие области (от 2000)
- для выявления нулевых указателей (от 0x00000000 до 0x0000FFFF ) 64 KB
- любое обращение туда - ошибка
- для кода и данных пользовательского режима
- располагается основной объем данных процесса, подгружаемые DLL и EXE модули
- ни один процесс не может получить доступ к этой области другого процесса
- ключ /3GB увеличивает его размер до 3 ГБ на х32 (без него - 1 ГБ)
- закрытый размером 64 KB
- его основная задача - упростить проверку того, что работа в области пользовательского режима мы не "залезем" в память для кода и данных режима ядра
- для кода и данных режима ядра
- сюда помещается код операционной системы, в том числе драйверы устрйств и код низкоуровневого управления потоками, файловой системой, сетевой поддержкой.
- все здесь доступно любому процессу, но только коду в режиме ядра (пользовательское обращение вызовет ошибку доступа)
Регионы в адресном пространстве
- аллоцирование при помощи VirtualAlloc в ВАПе (резервирование) только гранулярно (кратно 64КБ)
- далее нужно делать коммит при помощи той же функции (тут уже обязательна кратность страницам (4 КБ) )
что вообще происходит при запуске приложения
- система при запуске EXE файла считает этот EXE файлом куском памяти этого процесса и ничего никуда не копирует
стек потока
- он начинается в бОльших адресах и заканчивается на 0х08000000
- притом на странице 0х08001000 он кинет исключение StackOverflow
- и если исключение проигнорировать и продолжить работу то под 0x08000000 не выделяется физ память, потому все грохнется.
- у Win 2000 есть одна опасность - у них нет ограничителя на обращения в "отрицательные" области стека, и там произойдут обращения к, возможно, корректным олбластям памяти и никаких явных ошибок не будет видно
- поначалу все ставится так, что стек размеров 2 страницы, притом на страницу в которую растет стек ставится GUARD флаг, если до него дойдет - стек начнет расти. Исключение - 0x08001000 - на эту границу gurad никогда не ставится.
проецируемые файлы в память
- вместо того чтобы копировать себе часть/весь файл мы резервируем кусок адресного пространства, и его "перенаправляем" на файл лежащий на диске (никаких копирований)
- это позволяет
- быстро подгружать EXE и DLL части
- доступ к файлу с данными на диске без файлового считывания/вывода
- разделение доступа к этим данным между несколькими процессами на одной машине
- немного лирики о загрузке DLL
- есть так называемый "базовый адрес" (по умолчанию 0x10000000, но в DLL может быть указан в ручную)
- если он занят или в нем не удается выделить блок нужного размера
- если DLL типа FIXED то вообще fail, она не загрузится
- если не FIXED то она загрузится в найденный блок достаточного размера НО произойдет модификация адресов внутри DLL а это в Win2000 уйдет доп физ память и нкоторое время
кучи
- используются обычно для аллоцирования большого количества мелких объектов
- у процесса есть стандартная куча, по умолчания 1 МБ // ее используют Windows функции
- причины использования
- защита компонентов
- более эффективное управление памятью
- локальный доступ
- исключение издержек
- быстрое освобождение памяти в куче
- Low-Fragmentation Heap
- опция, которую можно включить для дефолтной кучи процесса или своей кучи
- как сделать
- получаем handle // ::CreateHeap или ::GetProcessHeap
- устанавлимваем нужный флаг // ::HeapSetInformation
- обозначает "при запросе менее 16KB он пытается найти самую маленькую область куда объект влезет и выделить там"
- не дружит с HEAP_NO_SERIALIZE
- начиная с Vista включена по дефолту.