Что возвращает HeapWalk

 
0
 
C++
ava
rudolfninja | 23.09.2013, 22:44
Доброго времени суток. Пришлось столкнуться с функцией HeapWalk. Пример взял с msdn.
Вот, что вернула функция:


Region
  4096 bytes committed
  258048 bytes uncommitted
  First block address: 0x14020598
  Last block address: 0x14060000

  Data portion begins at: 0x14020000
  Size: 1416 bytes
  Overhead: 0 bytes
  Region index: 0

Allocated block
  Data portion begins at: 0x140207d0
  Size: 10 bytes
  Overhead: 14 bytes
  Region index: 0

Allocated block
  Data portion begins at: 0x140207e8
  Size: 10 bytes
  Overhead: 14 bytes
  Region index: 0

Block

  Data portion begins at: 0x14020808
  Size: 2008 bytes
  Overhead: 16 bytes
  Region index: 0

Uncommitted range

  Data portion begins at: 0x14021000
  Size: 258048 bytes
  Overhead: 0 bytes
  Region index: 0


Кучу создавал так: _heap = HeapCreate(HEAP_GROWABLE, 0, 0);
Потом выделил в ней 2 блока по 10 байт каждый. Затем вызвал HeapWalk. Насколько я знаю, раз в структуре PROCESS_HEAP_ENTRY установлен флаг PROCESS_HEAP_REGION, значит элемент находится в начале непрерывной области нераспределенной виртуальной памяти. На компе 32ГБ ОЗУ, то есть оперативаня память не могла закончиться, что б система полезла в виртуальную.

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

Спасибо.
Comments (10)
ava
feodorv | 23.09.2013, 23:45 #
Интересно, зачем Вы задали флаг HEAP_GROWABLE, такого флага в описании функции HeapCreate не числится, это флаг для функции RtlCreateHeap.


Цитата (rudolfninja @  23.9.2013,  22:44 findReferencedText)
На компе 32ГБ ОЗУ, то есть оперативаня память не могла закончиться, что б система полезла в виртуальную. 

А при чём здесь ОЗУ? У каждого процесса своё виртуальное адресное пространство, неким прозрачным образом отображаемое на ОЗУ или страничный файл. Процесс непосредственно с ОЗУ дела не имеет.


Цитата (rudolfninja @  23.9.2013,  22:44 findReferencedText)
прокомментируйте, пожалуйста, то, что вернула функция HeapWalk

Первым делом в адресном пространстве процесса был зарезервирован регион (через VirtualAlloc) под нужды кучи, размером 262144 байт (262144 = 0x14060000 - 0x14020000 = 258048 + 4096). Вторым делом первая страница (4096 байт) этого региона передаётся процессу (теперь он может оттуда/туда читать/писать), остальное пространство блока остаётся недоступным для чтения/записи, но всё равно зарезервированным (никто другой эту область адресного пространства уже не сможет перезаказать). Часть переданной страницы адресного пространства ушло на управляющие структуры кучи (размером 1416 байт, 0x598 = 1432 байта, на что ушло ещё 16 байт, я не знаю). Тем не менее, первая аллокированная память пошла со смещением 2000 в регионе...

Ну и потом собственно аллокированная память: 
  • память в 24 байта со смещением 7d0 (2000)
  • память в 24 байта со смещением 7e8 (2024)
 
плюс оставшаяся незанятая непрерывная память в переданных страницах зарезервированного региона размером 2008+16 байт со смещением в регионе 2056 (0x1000 - 0x808 - 16 = 2008+16).
ava
rudolfninja | 24.09.2013, 09:46 #
Цитата
Куча - это регион зарезервированного адресного пространства. Первоначально большей его части физическая память не передается.

Так написано в книге Рихтера. То есть, получается, что под кучу выделается область виртуальной памяти, а потом, она передается ОЗУ?
ava
feodorv | 24.09.2013, 14:51 #
Цитата (rudolfninja @  24.9.2013,  10:46 findReferencedText)
Так написано в книге Рихтера

Тут лучше Руссиновича почитать)))


Цитата (rudolfninja @  24.9.2013,  10:46 findReferencedText)
а потом, она передается ОЗУ?

Эээ... Передаётся процессу, то есть страница адресного пространства процесса ассоциируется со страницей ОЗУ (или страничного файла), при этом переданная страница становится доступной на чтение/запись.

Если страница просто зарезервирована (но не передана), то с ОЗУ она никак не связана.

Механизм отображения страницы адресного пространства процесса на физическую память ОЗУ довольно затейлив, и целиком реализуется в режиме ядра. Пользовательский процесс может только попросить соответствующие подсистемы Windows передать (commit) память или высвободить (decommit) её.
ava
mega | 24.09.2013, 19:45 #
Цитата (feodorv @  24.9.2013,  16:51 findReferencedText)
Механизм отображения страницы адресного пространства процесса на физическую память ОЗУ довольно затейлив, и целиком реализуется в режиме ядра. Пользовательский процесс может только попросить соответствующие подсистемы Windows передать (commit) память или высвободить (decommit) её.

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

added later:
вернее - наоборот ))
ava
rudolfninja | 24.09.2013, 22:02 #
В общем, как я понял, память для кучи выделяется в виртуальном адресном пространстве процесса. При создании кучи (речь идет о пользовательской куче) в этом адресном пространстве (виртуальном) резервируется какой-то кусок памяти. Затем, при выделении памяти в куче, через HeapAlloc, часть зарезервированной области передается на физическую память, а остальная область просто остается зарезервированной и ждет, пока ее тоже будут использовать.
Если я все правильно понял, то возникает вопрос: чем куча отличается от виртуальной памяти (кроме того, что в куче меньшая гранулярность выделения памяти)? А если не прав - поправте, пожалуйста.
ava
feodorv | 24.09.2013, 23:30 #
Цитата (GremlinProg @  24.9.2013,  20:45 findReferencedText)
В общем-то, это не так со времен создания AWE

Ну, имелся в виду стандартный механизм управления памятью. И, по-моему, AWE недалеко от него ушёл)))


Цитата (rudolfninja @  24.9.2013,  23:02 findReferencedText)
чем куча отличается от виртуальной памяти

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


Цитата (rudolfninja @  24.9.2013,  23:02 findReferencedText)
кроме того, что в куче меньшая гранулярность выделения памяти

Одно из назначений кучи - оптимальное обращение с памятью, это да. Однако существуют реализации кучи, где каждый запрос на выделение памяти выполняется на новой странице адресного пространства процесса (что может привести к быстрому исчерпанию адресного пространства); такие кучи используются в отладочных целях.
ava
rudolfninja | 25.09.2013, 07:58 #
Вроде что-то прояснилось. Спасибо.
ava
mega | 25.09.2013, 11:27 #
Цитата (feodorv @  25.9.2013,  01:30 findReferencedText)
Ну, имелся в виду стандартный механизм управления памятью. И, по-моему, AWE недалеко от него ушёл)))

Само собой, если использовать только VirtualAlloc и VirtualFree (стандартный механизм управления памятью), то вклиниться в процесс "паджинга" не получится, как в сущности - в любой другой процесс, имеющий строгий API режима ядра.

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

Где это может пригодиться? Ну, даже самое банальное - там, где заранее известно, к каким страницам будет обращаться приложение, т.е. там, где отлов обращений через исключение по PAGE_GUARD может играть какую-то роль в производительности ПО. Или в 32-битном приложении, которому требуется более 4Гб ОЗУ.

...если они (более 4Гб ОЗУ), конечно доступны физически ))
ava
feodorv | 25.09.2013, 12:19 #
AWE, без сомнения, механизм полезный. Но всё равно приходится резервировать регион памяти в адресном пространстве процесса (а я, в сущности, только об этом) путём VirtualAlloc, получается этакое memory mapped RAM (по аналогии с memory mapped file). Приятно иметь невыгружаемый набор страниц)))


Цитата (GremlinProg @  25.9.2013,  12:27 findReferencedText)
...если они (более 4Гб ОЗУ), конечно доступны физически ))

Мда, памяти много не бывает)))
ava
mega | 25.09.2013, 19:48 #
Цитата (feodorv @  25.9.2013,  14:19 findReferencedText)
Но всё равно приходится резервировать регион памяти в адресном пространстве процесса (а я, в сущности, только об этом) путём VirtualAlloc

А вот только эта операция, пожалуй, и реализуется без какого-либо вмешательства "пользователем" в ядро, верно! Но это банальное резервирование диапазона страниц, без каких-либо дополнительных телодвижений, требующих подкачки или сброса страниц на диск.
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
advanced
Submit