我目前使用的是64位Windows7和Windows7。我正在使用一些PSAPI(process status api)函数来了解windows如何管理内存。
然而,我注意到QueryWorkingSet
包含了我无法阅读的条目(例如,第0页,而您无法阅读0x00000000
)。当在64位上尝试时,很明显的原因是:QueryWorkingSet
在32位上被窃听,因为地址被截断(因此多个页面0条目)。
但是,64位QueryWorkingSet
返回的某些条目也不可访问。为什么这个明显不可访问的内存显示为可访问?这是QueryWorkingSet
中的另一个bug吗?此外,为什么没有任何加载的模块显示在结果中?它们不是工作组的一部分吗?他们是……
这是一个小的示例程序,它使用seh尝试读取页面,并在页面不可读时报告该页面(而QueryWorkingSet
告诉我它是):
#include <windows.h>
#include <psapi.h>
#include <stdio.h>
char z;
int main(int argc, char **argv) {
unsigned int counter;
HANDLE thisProcess = GetCurrentProcess();
SYSTEM_INFO si;
PSAPI_WORKING_SET_INFORMATION wsi_1, *wsi;
DWORD wsi_size;
GetSystemInfo(&si);
wsi_1.NumberOfEntries = 0;
QueryWorkingSet(thisProcess, (LPVOID)&wsi_1, sizeof(wsi));
#if !defined(_WIN64)
wsi_1.NumberOfEntries--;
#endif
wsi_size = sizeof(PSAPI_WORKING_SET_INFORMATION)
+ sizeof(PSAPI_WORKING_SET_BLOCK) * wsi_1.NumberOfEntries;
wsi = (PSAPI_WORKING_SET_INFORMATION*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, wsi_size);
if (!QueryWorkingSet(thisProcess, (LPVOID)wsi, wsi_size)) {
printf("# Second QueryWorkingSet failed: %lu\n"
, GetLastError());
return 1;
}
for (counter = 0; counter < wsi->NumberOfEntries; counter++) {
unsigned long long page = (unsigned long long)wsi->WorkingSetInfo[counter].VirtualPage;
DWORD protection = (DWORD)wsi->WorkingSetInfo[counter].Protection;
__try {
if (*(char*)(page * si.dwPageSize) || TRUE) {
z = (protection & 5) ? '-' : 'T';
}
} __except(GetExceptionCode() == STATUS_ACCESS_VIOLATION) {
z = (protection & 5) ? 'F' : '-';
}
if (z == 'F') {
printf("%p %p : %c%c%c%c%c %c\n"
, (LPVOID)(page * si.dwPageSize)
, (LPVOID)((page + 1) * si.dwPageSize)
, protection & 16 ? 'G' : '-'
, protection & 8 ? 'V' : '-'
, protection & 4 ? 'w' : '-'
, protection & 2 ? 'x' : '-'
, protection & 1 ? 'r' : '-'
, z
);
}
}
return 0;
}
32位版本提供以下输出:
7DBED000 7DBEE000 : --w-- F
7DBEE000 7DBEF000 : --w-- F
7DC00000 7DC01000 : --w-- F
80008000 80009000 : --w-- F
01080000 01081000 : --w-- F
01000000 01001000 : --w-- F
00000000 00001000 : --w-- F
7DA00000 7DA01000 : --w-- F
40001000 40002000 : --w-- F
003F7000 003F8000 : --w-- F
003FF000 00400000 : --w-- F
003BA000 003BB000 : --w-- F
00001000 00002000 : --w-- F
003B9000 003BA000 : --w-- F
40000000 40001000 : --w-- F
00006000 00007000 : --w-- F
00002000 00003000 : --w-- F
00000000 00001000 : --w-- F
0039A000 0039B000 : --w-- F
003A6000 003A7000 : --w-- F
003A8000 003A9000 : --w-- F
003AC000 003AD000 : --w-- F
00003000 00004000 : --w-- F
64位版本提供了:
FFFFF6FB7DBED000 FFFFF6FB7DBEE000 : --w-- F
FFFFF6FB7DBEE000 FFFFF6FB7DBEF000 : --w-- F
FFFFF6FB7DC00000 FFFFF6FB7DC01000 : --w-- F
FFFFF6FB80008000 FFFFF6FB80009000 : --w-- F
FFFFF70001080000 FFFFF70001081000 : --w-- F
FFFFF70000000000 FFFFF70000001000 : --w-- F
FFFFF70001000000 FFFFF70001001000 : --w-- F
FFFFF7000107F000 FFFFF70001080000 : --w-- F
FFFFF6FB7DA0F000 FFFFF6FB7DA10000 : --w-- F
FFFFF6FB41FFF000 FFFFF6FB42000000 : --w-- F
FFFFF683FFFFF000 FFFFF68400000000 : --w-- F
FFFFF6FB40001000 FFFFF6FB40002000 : --w-- F
FFFFF680003FF000 FFFFF68000400000 : --w-- F
FFFFF6FB7DA00000 FFFFF6FB7DA01000 : --w-- F
FFFFF6FB40005000 FFFFF6FB40006000 : --w-- F
FFFFF68000A00000 FFFFF68000A01000 : --w-- F
FFFFF6FB40000000 FFFFF6FB40001000 : --w-- F
FFFFF68000000000 FFFFF68000001000 : --w-- F
FFFFF680003B9000 FFFFF680003BA000 : --w-- F
FFFFF68000001000 FFFFF68000002000 : --w-- F
FFFFF680003B6000 FFFFF680003B7000 : --w-- F
FFFFF680003B7000 FFFFF680003B8000 : --w-- F
FFFFF683FF7FA000 FFFFF683FF7FB000 : --w-- F
FFFFF683FF7EC000 FFFFF683FF7ED000 : --w-- F
FFFFF6FB41FFB000 FFFFF6FB41FFC000 : --w-- F
FFFFF680003F7000 FFFFF680003F8000 : --w-- F
FFFFF680003BA000 FFFFF680003BB000 : --w-- F
最佳答案
我假设这是由于本机api中的缺陷造成的。K32QueryWorkingSet
非常天真地使用了NtQueryVirtualMemory
,假设它可以将结果原样传递给调用者。根据this article,有问题的结果是指页面表和工作集条目,它们在内核空间是完全可读的,但不能从用户空间直接访问。
一个快速的解决方法是清理结果,这样在MmSystemRangeStart
下面找到的地址就被认为是有效的。此值只能在内核模式下读取,因此必须对用户模式应用程序进行“猜测”。对于Windows 7 64位,它是0xFFFF080000000000
。对于32位版本来说有点棘手(由于4GB的优化),但我不确定这个bug是否真的发生在那里。
关于windows - QueryWorkingSet的结果中包含无效页面,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8285506/