如何判断虚拟内存页是否已锁定
How to tell if a virtual memory page has been locked?
比如说,如果在某个时候我的进程中的虚拟内存范围被锁定为这样:
//Memory was reserved & committed as such
void* pMem = ::VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
//...
//And then
::VirtualLock(pMem, 4096);
因此,在我的进程中在虚拟内存中具有页面的任意地址,我可以判断它是否locked
吗?
通过使用
Win32 API这是不可能的。 但如果使用带有未记录MEMORY_INFORMATION_CLASS
值的ZwQueryVirtualMemory
- 这是可能的。 有关数据结构定义 - 请参阅 ntmmapi.h
我们需要将MemoryWorkingSetExInformation
与MEMORY_WORKING_SET_EX_BLOCK
一起使用并使用ULONG_PTR Locked : 1;
成员
演示测试:
NTSTATUS IsPageLocked(PVOID BaseAddress, BOOLEAN& Locked)
{
MEMORY_WORKING_SET_EX_INFORMATION mwsei = { BaseAddress };
NTSTATUS status = ZwQueryVirtualMemory(NtCurrentProcess(), 0, MemoryWorkingSetExInformation, &mwsei, sizeof(mwsei), 0);
if (0 <= status)
{
if (mwsei.VirtualAttributes.Valid)
{
Locked = mwsei.VirtualAttributes.Locked;
}
else
{
status = STATUS_INVALID_ADDRESS;
}
}
return status;
}
NTSTATUS IsPageLockedEx(PVOID BaseAddress, BOOLEAN& Locked)
{
NTSTATUS status = IsPageLocked(BaseAddress, Locked);
if (0 > status)
{
DbgPrint("IsPageLocked - error %xn", status);
}
else
{
DbgPrint("IsPageLocked = %xn", Locked);
}
return status;
}
void CheckVA()
{
if (PVOID pv = VirtualAlloc(NULL, PAGE_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))
{
BOOLEAN Locked;
NTSTATUS status = IsPageLockedEx(pv, Locked);
if (status == STATUS_INVALID_ADDRESS)
{
// at this point physical memory for pv not yet committed. reference memory for commit physical page
if (*(PBYTE)pv) __nop();
status = IsPageLockedEx(pv, Locked);
}
if (VirtualLock(pv, PAGE_SIZE))
{
IsPageLockedEx(pv, Locked);
if (VirtualUnlock(pv, PAGE_SIZE))
{
IsPageLockedEx(pv, Locked);
}
else
{
__debugbreak();
}
}
VirtualFree(pv, 0, MEM_RELEASE);
}
}
和 DbgPrint 输出
IsPageLocked - error c0000141
IsPageLocked = 0
IsPageLocked = 1
IsPageLocked = 0
对于将来看到这一点的任何人,XP和更高版本现在都包含这样做的API:QueryWorkingSet和QueryWorkingSetEx。
在PSAPI_WORKING_SET_EX_BLOCK结构中查找Locked
位,类似于依赖于ZwQueryVirtualMemory的答案。
相关文章:
- 如何检查线程是否锁定
- C++ 11 中的锁定是否保证访问数据的新鲜度?
- 同一互斥锁顺序上的锁定和解锁是否一致?
- 共享内存的升压容器是否实现锁定?
- 获取大小时是否必须锁定 std::queue?
- 我是否需要在 OpenSSL 1.1.0+ 中使用加密锁定函数来实现线程安全?
- 确定 SQLite 数据库是否已锁定
- 是否有必要锁定
- 锁定的互斥锁是否保护condition_variable和数据?
- C 删除对象,是否锁定
- 托管语言是否锁定本机库的刷新和重新加载变量?
- 是否可以锁定应用程序中常见控件使用的内存?
- 如何判断虚拟内存页是否已锁定
- 如何测试文件是否被锁定和/或只读而不打开?
- 如何判断当前过程是否已经锁定文件
- 我是否必须锁定我刚刚枚举的向量,或者我只在更改它时才这样做?
- 通知线程是否始终需要在修改期间锁定共享数据
- 如果其对象在多个线程中运行,我们是否需要锁定类成员功能
- 我的双重检查锁定模式实现是否正确?
- map是否锁定其节点以防止其他进程删除它们