#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
withMEM_COMMIT
. Вы можете отменить часть предыдущей фиксации.3. да, но вы не можете освободить неиспользуемую часть зарезервированного диапазона, верно?
MEM_RELEASE
требуетсяdwSize
быть0
4. @C.M. Правильно, вы можете отменить привязку отдельных страниц, но вы не можете отменить сохранение отдельных страниц.
Ответ №2:
Взгляните на источник в crt для _aligned_malloc
Windows / MSVC, очень просто использовать тот же метод для выравнивания виртуальной памяти, я бы даже сказал, просто замените его внутренний malloc
вызов (то же самое касается _aligned_free
), это позволяет выделять только один системный вызов.
Однако зачем вам такое масштабное выравнивание? Вы пытаетесь злоупотреблять шаблонами битовых адресов для быстрых блоков блоков памяти?