Новые Windows 8.1 API для управления виртуальной памятью: `DiscardVirtualMemory()` vs `VirtualAlloc()` и `MEM_RESET` и`MEM_RESET_UNDO`
Windows 8.1/Server 2012RC2 только что представила новые API для управления виртуальной памятью: OfferVirtualMemory()
, ReclaimVirtualMemory()
, DiscardVirtualMemory()
, что их использование довольно просто, просто посмотрев на их имена.
Я не могу понять, как эти API работают против VirtualAlloc()
плюс флаги MEM_RESET
а также MEM_RESET_UNDO
и каковы тонкие различия.
Для OfferVirtualMemory()
MSDN говорит, что очень похоже на VirtualAlloc()
+MEM_RESET
за исключением того, что он удаляет страницы из рабочего набора и ограничивает дальнейший доступ к страницам.
Итак, в основном это ограничивает доступ к страницам, и если я хочу получить доступ к этим страницам снова, я должен позвонить ReclaimVirtualMemory()
и это нормально, но не должно MEM_RESET
также удаляет страницы из рабочего набора? не должны MEM_RESET
действовать как POSIX MADV_DONTNEED
флаг madvise(2)
который в основном удаляет страницы из таблиц страниц процесса, и если в будущем я снова получу доступ к этим страницам, при доступе произойдет программная ошибка, и эти страницы будут снова перераспределены, инициализированы нулем.
Если это так, конечно, страницы удаляются из рабочего набора процесса, потому что они в основном освобождаются, даже если процесс сохраняет выделенные виртуальные адреса и видит их "зафиксированными".
Теперь посмотрим DiscardVirtualMemory()
: здесь MSDN ничего не говорит о MEM_RESET
флаг, но если я читаю описание этого API, кажется, действительно то же самое, что и VirtualAlloc()
+MEM_RESET
,
Итак, кто-нибудь знает, есть ли какие-то различия между этими API, и каковы правильные варианты использования этих тонких различий? Если они представили совершенно новый API, как DiscardVirtualMemory()
, должна быть какая-то разница со старым методом.
Если я хочу портировать приложение из POSIX, которое использует madvise(2)
с MADV_DONTNEED
а также MADV_WILLNEED
Каков наилучший способ имитировать это поведение POSIX? До сих пор я использовал VirtualAlloc()
+MEM_RESET
за MADV_DONTNEED
а также VirtualAlloc()
+MEM_RESET_UNDO
за MADV_WILLNEED
, Это нормально, или я могу лучше работать с этими новыми API?
1 ответ
Когда приложение снова обращается к области памяти, резервное ОЗУ восстанавливается, и содержимое памяти не определено.
Если я читаю между строк, это говорит:
- часть того, что было там, может быть еще там, когда вы получите к нему доступ
- разрешено давать вам инициализированные мусором страницы, когда эти страницы фиксируются
- если машина фактически была ограничена для памяти, некоторые страницы, вероятно, будут иногда инициализироваться нулем
Это не то, что произойдет, если вы сбросите диапазон виртуальных адресов с помощью более старого API. В этом случае есть гарантия предоставления нулевых инициализированных страниц при последующем доступе к этим страницам.
Это дает возможность окнам оказывать меньшее давление на пул обнуленных страниц, когда программы хотят быть очень хорошими, и сообщать окнам, что они могут выбрасывать некоторый свободный диапазон памяти.