此功能參考了ProcessHacker項目的代碼。
typedef struct _UINT64_DELTA { ULONG64 Value; ULONG64 Delta; } UINT64_DELTA, *PUINT64_DELTA; typedef struct _UINTPTR_DELTA { ULONG_PTR Value; ULONG_PTR Delta; } UINTPTR_DELTA, *PUINTPTR_DELTA; #define InitializeDelta(DltMgr) \ ((DltMgr)->Value = 0, (DltMgr)->Delta = 0) #define UpdateDelta(DltMgr, NewValue) \ ((DltMgr)->Delta = (NewValue) - (DltMgr)->Value, \ (DltMgr)->Value = (NewValue), (DltMgr)->Delta) typedef struct _SYSTEM_PERFORMANCE_INFORMATION { LARGE_INTEGER IdleProcessTime; LARGE_INTEGER IoReadTransferCount; LARGE_INTEGER IoWriteTransferCount; LARGE_INTEGER IoOtherTransferCount; ULONG IoReadOperationCount; ULONG IoWriteOperationCount; ULONG IoOtherOperationCount; ULONG AvailablePages; ULONG CommittedPages; ULONG CommitLimit; ULONG PeakCommitment; ULONG PageFaultCount; ULONG CopyOnWriteCount; ULONG TransitionCount; ULONG CacheTransitionCount; ULONG DemandZeroCount; ULONG PageReadCount; ULONG PageReadIoCount; ULONG CacheReadCount; ULONG CacheIoCount; ULONG DirtyPagesWriteCount; ULONG DirtyWriteIoCount; ULONG MappedPagesWriteCount; ULONG MappedWriteIoCount; ULONG PagedPoolPages; ULONG NonPagedPoolPages; ULONG PagedPoolAllocs; ULONG PagedPoolFrees; ULONG NonPagedPoolAllocs; ULONG NonPagedPoolFrees; ULONG FreeSystemPtes; ULONG ResidentSystemCodePage; ULONG TotalSystemDriverPages; ULONG TotalSystemCodePages; ULONG NonPagedPoolLookasideHits; ULONG PagedPoolLookasideHits; ULONG AvailablePagedPoolPages; ULONG ResidentSystemCachePage; ULONG ResidentPagedPoolPage; ULONG ResidentSystemDriverPage; ULONG CcFastReadNoWait; ULONG CcFastReadWait; ULONG CcFastReadResourceMiss; ULONG CcFastReadNotPossible; ULONG CcFastMdlReadNoWait; ULONG CcFastMdlReadWait; ULONG CcFastMdlReadResourceMiss; ULONG CcFastMdlReadNotPossible; ULONG CcMapDataNoWait; ULONG CcMapDataWait; ULONG CcMapDataNoWaitMiss; ULONG CcMapDataWaitMiss; ULONG CcPinMappedDataCount; ULONG CcPinReadNoWait; ULONG CcPinReadWait; ULONG CcPinReadNoWaitMiss; ULONG CcPinReadWaitMiss; ULONG CcCopyReadNoWait; ULONG CcCopyReadWait; ULONG CcCopyReadNoWaitMiss; ULONG CcCopyReadWaitMiss; ULONG CcMdlReadNoWait; ULONG CcMdlReadWait; ULONG CcMdlReadNoWaitMiss; ULONG CcMdlReadWaitMiss; ULONG CcReadAheadIos; ULONG CcLazyWriteIos; ULONG CcLazyWritePages; ULONG CcDataFlushes; ULONG CcDataPages; ULONG ContextSwitches; ULONG FirstLevelTbFills; ULONG SecondLevelTbFills; ULONG SystemCalls; } SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION; typedef struct _SYSTEM_BASIC_INFORMATION { ULONG Reserved; ULONG TimerResolution; ULONG PageSize; ULONG NumberOfPhysicalPages; ULONG LowestPhysicalPageNumber; ULONG HighestPhysicalPageNumber; ULONG AllocationGranularity; ULONG_PTR MinimumUserModeAddress; ULONG_PTR MaximumUserModeAddress; ULONG_PTR ActiveProcessorsAffinityMask; CCHAR NumberOfProcessors; } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
項目中需要引用ntdll.lib文件,此文件可以從ProcessHacker項目中找到。
ULONG64 total_time = 0; ULONG64 sys_time = 0; static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION CpuInformation[1024]; static SYSTEM_INFO sys_info; static UINT64_DELTA cpu_kernel_delta; static UINT64_DELTA cpu_user_delta; static UINT64_DELTA cpu_idle_delta; static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION cpu_totals; memset(&cpu_totals, 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); GetSystemInfo(&sys_info); NtQuerySystemInformation( SystemProcessorPerformanceInformation, &CpuInformation, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * (ULONG)sys_info.dwNumberOfProcessors, NULL ); for (int i = 0; i < (int)sys_info.dwNumberOfProcessors; i++) { SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION& cpu_info = CpuInformation[i]; // KernelTime includes idle time. LONGLONG dpc_time = cpu_info.Reserved1[0].QuadPart; LONGLONG interrupt_time = cpu_info.Reserved1[i].QuadPart; cpu_info.KernelTime.QuadPart -= cpu_info.IdleTime.QuadPart; cpu_info.KernelTime.QuadPart += dpc_time + interrupt_time; cpu_totals.Reserved1[0].QuadPart += dpc_time; cpu_totals.IdleTime.QuadPart += cpu_info.IdleTime.QuadPart; cpu_totals.Reserved2 += cpu_info.Reserved2; cpu_totals.Reserved1[1].QuadPart += cpu_info.Reserved1[1].QuadPart; cpu_totals.KernelTime.QuadPart += cpu_info.KernelTime.QuadPart; cpu_totals.UserTime.QuadPart += cpu_info.UserTime.QuadPart; } UpdateDelta(&cpu_kernel_delta, cpu_totals.KernelTime.QuadPart); UpdateDelta(&cpu_user_delta, cpu_totals.UserTime.QuadPart); UpdateDelta(&cpu_idle_delta, cpu_totals.IdleTime.QuadPart); total_time = cpu_kernel_delta.Delta + cpu_user_delta.Delta + cpu_idle_delta.Delta; sys_time = cpu_kernel_delta.Delta + cpu_user_delta.Delta; if (total_time) { return sys_time * 100.0 / total_time; } else { return 0.0; }
static SYSTEM_BASIC_INFORMATION system_basic_info; static long long mem_size = 0; if (mem_size != 0) return mem_size; static SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); NtQuerySystemInformation( SystemBasicInformation, &system_basic_info, sizeof(SYSTEM_BASIC_INFORMATION), NULL); mem_size = system_basic_info.NumberOfPhysicalPages; mem_size *= sys_info.dwPageSize; mem_size /= (1024 * 1024); //MB return mem_size;
static SYSTEM_PERFORMANCE_INFORMATION perf_info; static SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); NtQuerySystemInformation( SystemPerformanceInformation, &perf_info, sizeof(SYSTEM_PERFORMANCE_INFORMATION), NULL); long long available_size = perf_info.AvailablePages; available_size *= sys_info.dwPageSize; available_size /= (1024 * 1024); //MB long long mem_size = sys_mem_size(); if (mem_size != 0) { return (mem_size - available_size) * 100.0 / mem_size; } else { return 0.0; }