Выделение памяти Win32 с большим выравниванием

#winapi #memory-management #virtual-memory #memory-alignment

#winapi #управление памятью #виртуальная память #выравнивание памяти

Вопрос:

Мне нужно выделить большие области памяти (мегабайты) с большими выравниваниями (также потенциально в диапазоне мегабайт). Семейство функций VirtualAlloc, похоже, не предоставляет для этого опций.

Что я делаю в Linux для достижения этой цели, так это mmap большей области — достаточно большой, чтобы гарантировать, что в ней будет содержаться достаточно большая область с требуемым выравниванием, — а затем munmap области в начале и конце большой области, которые не нужны.

В качестве примера, допустим, мне нужно 4 мегабайта, выровненных по границе в 1 мегабайт (т. Е. Начало области, имеющей нули в младших 20 битах). Я бы выделил 5 мегабайт. Допустим, я получаю область 0x44ff000-0x49ff000. Внутри этой области содержится область 0x4500000-0x4900000, которая выровнена по границе в 1 мегабайт. Затем я бы munmap 0x44ff000-0x4500000 и 0x4900000-0x49ff000.

Могу ли я сделать что-то подобное в Win32? Если я использую VirtualProtect с PAGE_NOACCESS, будет ли освобождена память? Есть ли лучшее решение?

Комментарии:

1. Требование выравнивания для виртуальной памяти очень странно, это имеет значение только для физической памяти. Во всяком случае, это невозможно сделать в Windows. Но это не имеет значения, потому что вам нужно только зарезервировать выделения. Фиксация — это отдельный шаг. Также возможен запрос выделения на определенный счастливый адрес. Используйте VirtualAlloc().

Ответ №1:

Да, вы можете использовать тот же метод. VirtualAlloc большой диапазон как MEM_RESERVE . Найдите поддиапазон, который соответствующим образом выровнен, и вызовите VirtualAlloc второй раз поддиапазон с MEM_COMMIT помощью .

Комментарии:

1. Возможно ли освободить неиспользуемую часть диапазона? (аналогично munmap() вызовам, упомянутым в исходном сообщении) Согласно моему чтению VirtualFree() документов — это невозможно…

2. @C.M. VirtualFree может использоваться с MEM_DECOMMIT , чтобы отменить эффект более раннего VirtualAlloc with MEM_COMMIT . Вы можете отменить часть предыдущей фиксации.

3. да, но вы не можете освободить неиспользуемую часть зарезервированного диапазона, верно? MEM_RELEASE требуется dwSize быть 0

4. @C.M. Правильно, вы можете отменить привязку отдельных страниц, но вы не можете отменить сохранение отдельных страниц.

Ответ №2:

Взгляните на источник в crt для _aligned_malloc Windows / MSVC, очень просто использовать тот же метод для выравнивания виртуальной памяти, я бы даже сказал, просто замените его внутренний malloc вызов (то же самое касается _aligned_free ), это позволяет выделять только один системный вызов.

Однако зачем вам такое масштабное выравнивание? Вы пытаетесь злоупотреблять шаблонами битовых адресов для быстрых блоков блоков памяти?