Private WS
Private WS,专用工作集,即任务管理器默认显示的[内存大小][6],微软并没有给出API来获取这个值,直到我阅读了[Process Hacker][6]的源码。向作者致敬,开源如此优秀的作品。
Process Hacker链接:Process Hacker
数据类型
typedef struct _MEMORY_WORKING_SET_BLOCK
{
ULONG_PTR Protection : 5;
ULONG_PTR ShareCount : 3;
ULONG_PTR Shared : 1;
ULONG_PTR Node : 3;
#ifdef _WIN64
ULONG_PTR VirtualPage : 52;
#else
ULONG VirtualPage : 20;
#endif
} MEMORY_WORKING_SET_BLOCK, *PMEMORY_WORKING_SET_BLOCK;
typedef struct _MEMORY_WORKING_SET_INFORMATION
{
ULONG_PTR NumberOfEntries;
MEMORY_WORKING_SET_BLOCK WorkingSetInfo[1];
} MEMORY_WORKING_SET_INFORMATION, *PMEMORY_WORKING_SET_INFORMATION;
MEMORY_INFORMATION_CLASS
typedef enum _MEMORY_INFORMATION_CLASS
{
MemoryBasicInformation, // MEMORY_BASIC_INFORMATION
MemoryWorkingSetInformation, // MEMORY_WORKING_SET_INFORMATION
MemoryMappedFilenameInformation, // UNICODE_STRING
MemoryRegionInformation, // MEMORY_REGION_INFORMATION
MemoryWorkingSetExInformation, // MEMORY_WORKING_SET_EX_INFORMATION
MemorySharedCommitInformation, // MEMORY_SHARED_COMMIT_INFORMATION
MemoryImageInformation // MEMORY_IMAGE_INFORMATION
} MEMORY_INFORMATION_CLASS;
实现代码
NTSTATUS GetProcessWorkingSetInformation(
_In_ HANDLE ProcessHandle,
_Out_ PMEMORY_WORKING_SET_INFORMATION *WorkingSetInformation
)
{
NTSTATUS status = STATUS_SUCCESS;
PVOID buffer = NULL;
SIZE_T bufferSize = 0;
bufferSize = 0x800;
buffer = malloc(bufferSize);
while ((status = NtQueryVirtualMemory(
ProcessHandle,
NULL,
MemoryWorkingSetInformation,
buffer,
bufferSize,
NULL
)) == STATUS_INFO_LENGTH_MISMATCH)
{
free(buffer);
bufferSize *= 2;
// Fail if we're resizing the buffer to something very large.
if (bufferSize > PH_LARGE_BUFFER_SIZE)
return STATUS_INSUFFICIENT_RESOURCES;
buffer = malloc(bufferSize);
}
if (!NT_SUCCESS(status))
{
free(buffer);
return status;
}
*WorkingSetInformation = (PMEMORY_WORKING_SET_INFORMATION)buffer;
return status;
}
NTSTATUS GetProcessWsCounters(
_In_ HANDLE ProcessHandle,
_Out_ PPROCESS_WS_COUNTERS WsCounters
)
{
NTSTATUS status = STATUS_SUCCESS;
PMEMORY_WORKING_SET_INFORMATION wsInfo = NULL;
PROCESS_WS_COUNTERS wsCounters = {0};
ULONG i = 0;
if (!NT_SUCCESS(status = GetProcessWorkingSetInformation(
ProcessHandle,
&wsInfo
)))
return status;
memset(&wsCounters, 0, sizeof(PROCESS_WS_COUNTERS));
for (i = 0; i < wsInfo->NumberOfEntries; i++)
{
wsCounters.NumberOfPages++;
if (wsInfo->WorkingSetInfo[i].ShareCount > 1)
wsCounters.NumberOfSharedPages++;
if (wsInfo->WorkingSetInfo[i].ShareCount == 0)
wsCounters.NumberOfPrivatePages++;
if (wsInfo->WorkingSetInfo[i].Shared)
wsCounters.NumberOfShareablePages++;
}
free(wsInfo);
*WsCounters = wsCounters;
return status;
}
调用
PROCESS_WS_COUNTERS wsCounters = { 0 };
SIZE_T PrivateWS = 0;
//// Try to open a process handle with PROCESS_QUERY_INFORMATION access for
// WS information.
GetProcessWsCounters(hProcess, &wsCounters);
PrivateWS = wsCounters.NumberOfPrivatePages * PAGE_SIZE;
How to get page size
SYSTEM_INFO SysInfo = { 0 };
DWORD dwPageSize = 0;
GetSystemInfo( &SysInfo );
dwPageSize = SysInfo.dwPageSize;