我在google上发现了这个代码,它计算了win10上当前进程的使用率,但是我正在寻找的是每个进程的CPU使用率的百分比列表。 我使用GetCurrentProcess()来处理当前进程的句柄。 有没有办法检索每个进程的句柄?我正在编写一个列出正在运行的进程的代码,并为每个人计算使用内存。 然后我需要计算每个人的CPU使用率,但我没有发现任何东西在谷歌。
static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU; static int numProcessors; static HANDLE self; void init(){ SYSTEM_INFO sysInfo; FILETIME ftime, fsys, fuser; GetSystemInfo(&sysInfo); numProcessors = sysInfo.dwNumberOfProcessors; GetSystemTimeAsFileTime(&ftime); memcpy(&lastCPU, &ftime, sizeof(FILETIME)); self = GetCurrentProcess(); GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser); memcpy(&lastSysCPU, &fsys, sizeof(FILETIME)); memcpy(&lastUserCPU, &fuser, sizeof(FILETIME)); } double getCurrentValue(){ FILETIME ftime, fsys, fuser; ULARGE_INTEGER now, sys, user; long double percent; GetSystemTimeAsFileTime(&ftime); memcpy(&now, &ftime, sizeof(FILETIME)); GetProcessTimes(GetCurrentProcess(), &ftime, &ftime, &fsys, &fuser); memcpy(&sys, &fsys, sizeof(FILETIME)); memcpy(&user, &fuser, sizeof(FILETIME)); percent = (sys.QuadPart - lastSysCPU.QuadPart) + (user.QuadPart - lastUserCPU.QuadPart); percent /= (now.QuadPart - lastCPU.QuadPart); percent /= numProcessors; lastCPU = now; lastUserCPU = user; lastSysCPU = sys; return percent * 100; } I'm able to have the list of all running processes but i'm looking for to calculate cpu usage for every process. Suggestions?
好的,为了有效的编码,这个任务需要使用SystemProcessInformation
类的NtQueryInformationProcess
类。 我们在这里得到了SYSTEM_PROCESS_INFORMATION
数组。 这里我们已经有了:
LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER coreelTime;
在PROCESSENTRY32
没有这个成员。 toolhelp函数简单地删除这个成员。 没有它,我们需要打开每个进程,调用GetProcessTimes
等与NtQueryInformationProcess
都变得更加有效和简单。 总体思路 – 我们需要维护进程列表,并定期调用NtQueryInformationProcess
来添加新创建的进程并删除死亡。
// for debug only 0 <= cpuUsage <= 1000 void PrintCpuUsage(ULONG cpuUsage, PCUNICODE_STRING Name) { ULONG p = cpuUsage / 10; DbgPrint("%02u.%u %wZ\n", p, cpuUsage - p * 10, Name); } struct PROCESS_ENTRY : LIST_ENTRY, UNICODE_STRING { LARGE_INTEGER _CreateTime, _RunTime; union { LARGE_INTEGER _Delta; ULONG _cpuUsage; }; HANDLE _UniqueProcessId; HANDLE _InheritedFromUniqueProcessId; BOOLEAN _bEnumerated; PROCESS_ENTRY() { RtlInitUnicodeString(this, 0); InitializeListHead(this); _RunTime.QuadPart = 0; _UniqueProcessId = 0; } ~PROCESS_ENTRY() { DbgPrint("--%08x(%08x) %wZ\n", _UniqueProcessId, _InheritedFromUniqueProcessId, static_cast<UNICODE_STRING*>(this)); RtlFreeUnicodeString(this); RemoveEntryList(this); } NTSTATUS Init(PSYSTEM_PROCESS_INFORMATION pspi) { _UniqueProcessId = pspi->UniqueProcessId; _InheritedFromUniqueProcessId = pspi->InheritedFromUniqueProcessId; _CreateTime = pspi->CreateTime; DbgPrint("++%08x(%08x) %wZ\n", _UniqueProcessId, _InheritedFromUniqueProcessId, &pspi->ImageName); return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &pspi->ImageName, this); } LONGLONG UpdateProcess(PSYSTEM_PROCESS_INFORMATION pspi) { _bEnumerated = TRUE; pspi->coreelTime.QuadPart += pspi->UserTime.QuadPart; _Delta.QuadPart = pspi->coreelTime.QuadPart - _RunTime.QuadPart; _RunTime.QuadPart = pspi->coreelTime.QuadPart; return _Delta.QuadPart; } void CalcCpuUsage(LONGLONG QuadPart) { _bEnumerated = FALSE; _cpuUsage = (ULONG)((_Delta.QuadPart * 1000) / QuadPart ); if (_cpuUsage && _UniqueProcessId) { PrintCpuUsage(_cpuUsage, this); } } }; struct PROCES_LIST : public LIST_ENTRY { LIST_ENTRY _ListHead; PROCESS_ENTRY IdleProcess; BOOL _bValid; PROCES_LIST() { InitializeListHead(&_ListHead); _bValid = FALSE; } LONGLONG UpdateOrAddNewProcess(PSYSTEM_PROCESS_INFORMATION pspi); void RemoveDiedEntries(LONGLONG QuadPart); void EnumPro(); ~PROCES_LIST() { RemoveDiedEntries(0); } }; LONGLONG PROCES_LIST::UpdateOrAddNewProcess(PSYSTEM_PROCESS_INFORMATION pspi) { PROCESS_ENTRY* pe; PLIST_ENTRY head = &_ListHead, entry = head; HANDLE UniqueProcessId = pspi->UniqueProcessId; while ((entry = entry->Flink) != head) { pe = static_cast<PROCESS_ENTRY*>(entry); if (pe->_UniqueProcessId == UniqueProcessId && pe->_CreateTime.QuadPart == pspi->CreateTime.QuadPart) { return pe->UpdateProcess(pspi); } } if (pe = new PROCESS_ENTRY) { if (0 <= pe->Init(pspi)) { InsertTailList(head, pe); return pe->UpdateProcess(pspi); } delete pe; } return 0; } void PROCES_LIST::RemoveDiedEntries(LONGLONG QuadPart) { PLIST_ENTRY head = &_ListHead, entry = head->Flink; while (entry != head) { PROCESS_ENTRY* pe = static_cast<PROCESS_ENTRY*>(entry); entry = entry->Flink; if (pe->_bEnumerated) { pe->CalcCpuUsage(QuadPart); } else { delete pe; } } } void PROCES_LIST::EnumPro() { ULONG cb = 0, rcb = 0x10000; PVOID stack = alloca(guz);// volatile UCHAR guz; union { PVOID buf; PBYTE pb; PSYSTEM_PROCESS_INFORMATION pspi; }; NTSTATUS status; do { if (cb < rcb) { cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack); } if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &rcb))) { LONGLONG QuadPart = 0; ULONG NextEntryOffset = 0; do { pb += NextEntryOffset; if (pspi->UniqueProcessId) { QuadPart += UpdateOrAddNewProcess(pspi); } else { QuadPart += IdleProcess.UpdateProcess(pspi); } } while (NextEntryOffset = pspi->NextEntryOffset); RemoveDiedEntries(QuadPart); IdleProcess.CalcCpuUsage(QuadPart); if (_bValid) { static UNICODE_STRING empty; PrintCpuUsage(1000 - IdleProcess._cpuUsage, &empty); } else { _bValid = TRUE; } } } while (status == STATUS_INFO_LENGTH_MISMATCH); }