//这是头文件cpu.h==================
#include <stdio.h>#include <windows.h>
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004)typedef LONG NTSTATUS;#define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))
//self def struct.typedef struct CpuData { DWORD dwPID; UINT cpuusage; __int64 lastidle; __int64 lastsys; LARGE_INTEGER qCputime; LARGE_INTEGER qKernelTime; LARGE_INTEGER qUserTime;} *pCpuData;
typedef struct _SYSTEM_PERFORMANCE_INFORMATION{ LARGE_INTEGER IdleTime; //CPU空闲时间; LARGE_INTEGER ReadTransferCount; //I/O读操作数目; LARGE_INTEGER WriteTransferCount; //I/O写操作数目; LARGE_INTEGER OtherTransferCount; //I/O其他操作数目; ULONG ReadOperationCount; //I/O读数据数目; ULONG WriteOperationCount; //I/O写数据数目; ULONG OtherOperationCount; //I/O其他操作数据数目; ULONG AvailablePages; //可获得的页数目; ULONG TotalCommittedPages; //总共提交页数目; ULONG TotalCommitLimit; //已提交页数目; ULONG PeakCommitment; //页提交峰值; ULONG PageFaults; //页故障数目; ULONG WriteCopyFaults; //Copy-On-Write故障数目; ULONG TransitionFaults; //软页故障数目; ULONG CacheTransitionFaults; //================= ULONG DemandZeroFaults; //需求0故障数; ULONG PagesRead; //读页数目; ULONG PageReadIos; //读页I/O操作数; ULONG CacheReadFaults; ULONG CacheIoFaults; ULONG PagefilePagesWritten; //已写页文件页数; ULONG PagefilePageWriteIos; //已写页文件操作数; ULONG MappedFilePagesWritten; //已写映射文件页数; ULONG MappedFileWriteIos; //已写映射文件操作数; ULONG PagedPoolUsage; //分页池使用; ULONG NonPagedPoolUsage; //非分页池使用; ULONG PagedPoolAllocs; //分页池分配情况; ULONG PagedPoolFrees; //分页池释放情况; ULONG NonPagedPoolAllocs; //非分页池分配情况; ULONG NonPagedPoolFress; //非分页池释放情况; ULONG TotalFreeSystemPtes; //系统页表项释放总数; ULONG SystemCodePage; //操作系统代码页数; ULONG TotalSystemDriverPages; //可分页驱动程序页数; ULONG TotalSystemCodePages; //操作系统代码页总数; ULONG SmallNonPagedLookasideListAllocateHits; //小非分页侧视列表分配次数; ULONG SmallPagedLookasideListAllocateHits; //小分页侧视列表分配次数; ULONG Reserved3; ULONG MmSystemCachePage; //系统缓存页数; ULONG PagedPoolPage; //分页池页数; ULONG SystemDriverPage; //可分页驱动页数; ULONG FastReadNoWait; //异步快速读数目; ULONG FastReadWait; //同步快速读数目; ULONG FastReadResourceMiss; //快速读资源冲突数; ULONG FastReadNotPossible; //快速读失败数; ULONG FastMdlReadNoWait; //异步MDL快速读数目; ULONG FastMdlReadWait; //同步MDL快速读数目; ULONG FastMdlReadResourceMiss; //MDL读资源冲突数; ULONG FastMdlReadNotPossible; //MDL读失败数; ULONG MapDataNoWait; //异步映射数据次数; ULONG MapDataWait; //同步映射数据次数; ULONG MapDataNoWaitMiss; //异步映射数据冲突次数; ULONG MapDataWaitMiss; //同步映射数据冲突次数; ULONG PinMappedDataCount; //牵制映射数据数目; ULONG PinReadNoWait; //牵制异步读数目; ULONG PinReadWait; //牵制同步读数目; ULONG PinReadNoWaitMiss; //牵制异步读冲突数目; ULONG PinReadWaitMiss; //牵制同步读冲突数目; ULONG CopyReadNoWait; //异步拷贝读次数; ULONG CopyReadWait; //同步拷贝读次数; ULONG CopyReadNoWaitMiss; //异步拷贝读故障次数; ULONG CopyReadWaitMiss; //同步拷贝读故障次数; ULONG MdlReadNoWait; //异步MDL读次数; ULONG MdlReadWait; //同步MDL读次数; ULONG MdlReadNoWaitMiss; //异步MDL读故障次数; ULONG MdlReadWaitMiss; //同步MDL读故障次数; ULONG ReadAheadIos; //向前读操作数目; ULONG LazyWriteIos; //LAZY写操作数目; ULONG LazyWritePages; //LAZY写页文件数目; ULONG DataFlushes; //缓存刷新次数; ULONG DataPages; //缓存刷新页数; ULONG ContextSwitches; //环境切换数目; ULONG FirstLevelTbFills; //第一层缓冲区填充次数; ULONG SecondLevelTbFills; //第二层缓冲区填充次数; ULONG SystemCall; //系统调用次数;}SYSTEM_PERFORMANCE_INFORMATION,*PSYSTEM_PERFORMANCE_INFORMATION;
typedef struct _SYSTEM_TIMEOFDAY_INFORMATION{ LARGE_INTEGER BootTime; LARGE_INTEGER CurrentTime; LARGE_INTEGER TimeZoneBias; ULONG TimeZoneId; ULONG Reserved;} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION;
//include sys headertypedef struct _THREAD_INFO{ LARGE_INTEGER CreateTime; DWORD dwUnknown1; DWORD dwStartAddress; DWORD StartEIP; DWORD dwOwnerPID; DWORD dwThreadId; DWORD dwCurrentPriority; DWORD dwBasePriority; DWORD dwContextSwitches; DWORD Unknown; DWORD WaitReason; }THREADINFO, *PTHREADINFO;
typedef struct _UNICODE_STRING{ USHORT Length; USHORT MaxLength; PWSTR Buffer;} UNICODE_STRING;
typedef struct _SYSTEM_PROCESS_INFORMATION { DWORD dwNextEntryOffset; DWORD dwNumberOfThreads; LARGE_INTEGER qSpareLi1; LARGE_INTEGER qSpareLi2; LARGE_INTEGER qSpareLi3; LARGE_INTEGER qCreateTime; LARGE_INTEGER qUserTime; LARGE_INTEGER qKernelTime; UNICODE_STRING ImageName; int nBasePriority; DWORD dwProcessId; DWORD dwInheritedFromUniqueProcessId; DWORD dwHandleCount; DWORD dwSessionId; ULONG dwSpareUl3; SIZE_T tPeakVirtualSize; SIZE_T tVirtualSize; DWORD dwPageFaultCount; DWORD dwPeakWorkingSetSize; DWORD dwWorkingSetSize; SIZE_T tQuotaPeakPagedPoolUsage; SIZE_T tQuotaPagedPoolUsage; SIZE_T tQuotaPeakNonPagedPoolUsage; SIZE_T tQuotaNonPagedPoolUsage; SIZE_T tPagefileUsage; SIZE_T tPeakPagefileUsage; SIZE_T tPrivatePageCount; LARGE_INTEGER qReadOperationCount; LARGE_INTEGER qWriteOperationCount; LARGE_INTEGER qOtherOperationCount; LARGE_INTEGER qReadTransferCount; LARGE_INTEGER qWriteTransferCount; LARGE_INTEGER qOtherTransferCount; }SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { LARGE_INTEGER IdleTime; LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER DpcTime; LARGE_INTEGER InterruptTime; ULONG InterruptCount;} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
typedef struct _SYSTEM_BASIC_INFORMATION{ DWORD dwUnknown1; // 0 ULONG uKeMaximumIncrement; // x86: 0x0002625A or 0x00018730 ULONG uPageSize; // bytes ULONG uMmNumberOfPhysicalPages; ULONG uMmLowestPhysicalPage; ULONG uMmHighestPhysicalPage; ULONG uAllocationGranularity; // bytes PVOID pLowestUserAddress; PVOID pMmHighestUserAddress; LONG * uKeActiveProcessors; BYTE bKeNumberProcessors; //系统cpu个数 BYTE bUnknown2; WORD wUnknown3;} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
=============================================================================
//下面是cpu.cpp文件============================================================
#include <iostream>
using namespace std;#include "cpu.h" #define SystemBasicInformation 0#define SystemPerformanceInformation 2#define SystemTimeOfDayInformation 3#define SystemProcessInformation 5 //5 per process SystemProcessesAndThreadsInformation#define SystemProcessorPerformanceInformation 8 //8 per cpu SystemProcessorCounters
CRITICAL_SECTION PerfDataCriticalSection; CpuData *pPerfDataOld = NULL; /* Older perf data (saved to establish delta values) */ CpuData *pPerfData = NULL; /* Most recent copy of perf data */ ULONG ProcessCountOld = 0; ULONG ProcessCount = 0; SYSTEM_BASIC_INFORMATION SystemBasicInfo; SYSTEM_PERFORMANCE_INFORMATION SystemPerfInfo; PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SystemProcessorTimeInfo = NULL; LARGE_INTEGER liOldIdleTime = {{0,0}}; double dbIdleTime; double dbKernelTime; double dbSystemTime; double OldKernelTime = 0; LARGE_INTEGER liOldSystemTime = {{0,0}};
//long (WINAPI *NtQuerySystemInformation )( DWORD, PVOID, DWORD, DWORD* ); typedef LONG (WINAPI *Fun_NtQuerySystemInformation) ( int SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT ULONG * pReturnLength OPTIONAL);Fun_NtQuerySystemInformation NtQuerySystemInformation;
BOOL PerfDataInitialize(void) { SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY}; NTSTATUS status; //typedef LONG NTSTATUS; InitializeCriticalSection(&PerfDataCriticalSection); NtQuerySystemInformation = (Fun_NtQuerySystemInformation)GetProcAddress(LoadLibraryA("ntdll.dll"), "NtQuerySystemInformation"); //这里也可以通过GetModuleHandle()获取实例句柄 /* * Get number of processors in the system */ status = NtQuerySystemInformation(SystemBasicInformation, &SystemBasicInfo, sizeof(SystemBasicInfo), NULL); if (status != NO_ERROR) return FALSE; /* * Create the SYSTEM Sid */ return TRUE; }
void PerfDataUninitialize(void) { DeleteCriticalSection(&PerfDataCriticalSection); }
void GetAllProcCPUUsage() { ULONG ulSize; LONG status; LPBYTE pBuffer; ULONG BufferSize; PSYSTEM_PROCESS_INFORMATION pSPI; pCpuData pPDOld; ULONG Idx, Idx2; HANDLE hProcess; HANDLE hProcessToken; double CurrentKernelTime; SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo; SYSTEM_TIMEOFDAY_INFORMATION SysTimeInfo; PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SysProcessorTimeInfo; ULONG Buffer[64]; /* must be 4 bytes aligned! */ /* Get new system time */ status = NtQuerySystemInformation (SystemTimeOfDayInformation, &SysTimeInfo, sizeof(SysTimeInfo), 0); if (status != NO_ERROR) //如果返回值status不为0,则表示成功 return; /* Get new CPU's idle time */ status = NtQuerySystemInformation (SystemPerformanceInformation, &SysPerfInfo, sizeof(SysPerfInfo), NULL); if (status != NO_ERROR) return; /* Get processor time information */ HANDLE myHeadHandle = GetProcessHeap(); if(NULL != myHeadHandle) { SysProcessorTimeInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) HeapAlloc(myHeadHandle, 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * SystemBasicInfo.bKeNumberProcessors); } status = NtQuerySystemInformation( SystemProcessorPerformanceInformation, SysProcessorTimeInfo, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * SystemBasicInfo.bKeNumberProcessors, &ulSize); if (status != NO_ERROR) return; /* Get process information * We don't know how much data there is so just keep * increasing the buffer size until the call succeeds */ BufferSize = 0; do { BufferSize += 0x10000; pBuffer = (LPBYTE)HeapAlloc(myHeadHandle, 0, BufferSize); status = NtQuerySystemInformation(SystemProcessInformation, pBuffer, BufferSize, &ulSize); if (status == STATUS_INFO_LENGTH_MISMATCH) { HeapFree(myHeadHandle, 0, pBuffer); } } while (status == STATUS_INFO_LENGTH_MISMATCH); EnterCriticalSection(&PerfDataCriticalSection); /* * Save system performance info */ memcpy(&SystemPerfInfo, &SysPerfInfo, sizeof(SYSTEM_PERFORMANCE_INFORMATION)); /* * Save system processor time info */ if (SystemProcessorTimeInfo) { HeapFree(myHeadHandle, 0, SystemProcessorTimeInfo); } SystemProcessorTimeInfo = SysProcessorTimeInfo; /* * Save system handle info */ for (CurrentKernelTime = 0, Idx = 0; Idx < (ULONG)SystemBasicInfo.bKeNumberProcessors; Idx++) { CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].KernelTime); CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].DpcTime); CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].InterruptTime); } /* If it's a first call - skip idle time calcs */ if (liOldIdleTime.QuadPart != 0) { /* CurrentValue = NewValue - OldValue */ dbIdleTime = Li2Double(SysPerfInfo.IdleTime) - Li2Double(liOldIdleTime); dbKernelTime = CurrentKernelTime - OldKernelTime; dbSystemTime = Li2Double(SysTimeInfo.CurrentTime) - Li2Double(liOldSystemTime); /* CurrentCpuIdle = IdleTime / SystemTime */ dbIdleTime = dbIdleTime / dbSystemTime; dbKernelTime = dbKernelTime / dbSystemTime; /* CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors */ dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SystemBasicInfo.bKeNumberProcessors; /* + 0.5; */ dbKernelTime = 100.0 - dbKernelTime * 100.0 / (double)SystemBasicInfo.bKeNumberProcessors; /* + 0.5; */ } /* Store new CPU's idle and system time */ liOldIdleTime = SysPerfInfo.IdleTime; liOldSystemTime = SysTimeInfo.CurrentTime; OldKernelTime = CurrentKernelTime; /* Determine the process count * We loop through the data we got from NtQuerySystemInformation * and count how many structures there are (until RelativeOffset is 0) */ ProcessCountOld = ProcessCount; ProcessCount = 0; pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer; while (pSPI) { ProcessCount++; if (pSPI->dwNextEntryOffset == 0) break; pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->dwNextEntryOffset); } /* Now alloc a new PERFDATA array and fill in the data */ if (pPerfDataOld) { HeapFree(GetProcessHeap(), 0, pPerfDataOld); } pPerfDataOld = pPerfData; pPerfData = (pCpuData)HeapAlloc(GetProcessHeap(), 0, sizeof(CpuData) * ProcessCount); pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer; for (Idx = 0; Idx < ProcessCount; Idx++) { /* Get the old perf data for this process (if any) */ /* so that we can establish delta values */ pPDOld = NULL; for (Idx2=0; Idx2 < ProcessCountOld; Idx2++) { if (pPerfDataOld[Idx2].dwPID == pSPI->dwProcessId) { pPDOld = &pPerfDataOld[Idx2]; break; } } /* Clear out process perf data structure */ memset(&pPerfData[Idx], 0, sizeof(CpuData)); pPerfData[Idx].dwPID = pSPI->dwProcessId; if (pPDOld) { double CurTime = Li2Double(pSPI->qKernelTime) + Li2Double(pSPI->qUserTime); double OldTime = Li2Double(pPDOld->qKernelTime) + Li2Double(pPDOld->qUserTime); double CpuTime = (CurTime - OldTime) / dbSystemTime; CpuTime = CpuTime * 100.0 / (double)SystemBasicInfo.bKeNumberProcessors; /* + 0.5; */ pPerfData[Idx].cpuusage = (ULONG)CpuTime; } pPerfData[Idx].qCputime.QuadPart = pSPI->qUserTime.QuadPart + pSPI->qKernelTime.QuadPart; if (pSPI->dwProcessId != NULL) { hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | READ_CONTROL, FALSE, PtrToUlong(pSPI->dwProcessId)); if (hProcess) { /* don't query the information of the system process. It's possible but returns Administrators as the owner of the process instead of SYSTEM */ if (pSPI->dwProcessId != 0x4) { if (OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken)) { DWORD RetLen = 0; BOOL Ret; Ret = GetTokenInformation(hProcessToken, TokenUser, (LPVOID)Buffer, sizeof(Buffer), &RetLen); CloseHandle(hProcessToken); } } CloseHandle(hProcess); } } pPerfData[Idx].qUserTime.QuadPart = pSPI->qUserTime.QuadPart; pPerfData[Idx].qKernelTime.QuadPart = pSPI->qKernelTime.QuadPart; pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->dwNextEntryOffset); } HeapFree(GetProcessHeap(), 0, pBuffer); LeaveCriticalSection(&PerfDataCriticalSection); }
int PerfGetIndexByProcessId(DWORD dwProcessId) { int Index, FoundIndex = -1; EnterCriticalSection(&PerfDataCriticalSection); for (Index = 0; Index < (int)ProcessCount; Index++) { if ((DWORD)pPerfData[Index].dwPID == dwProcessId) { FoundIndex = Index; break; } } LeaveCriticalSection(&PerfDataCriticalSection); return FoundIndex; }
ULONG PerfDataGetCPUUsage(DWORD dwProcessId) { ULONG CpuUsage; int Index, FoundIndex = -1; EnterCriticalSection(&PerfDataCriticalSection); for (Index = 0; Index < (int)ProcessCount; Index++) { if ((DWORD)pPerfData[Index].dwPID == dwProcessId) { FoundIndex = Index; break; } } if (Index < (int)ProcessCount) CpuUsage = pPerfData[Index].cpuusage; else CpuUsage = 0; LeaveCriticalSection(&PerfDataCriticalSection); return CpuUsage; }
int main(void){ PerfDataInitialize(); while(1) { GetAllProcCPUUsage(); printf("PID:0 CPU:%u/n", PerfDataGetCPUUsage(0)); printf("PID:2608 CPU:%u/n", PerfDataGetCPUUsage(2608)); Sleep(1000); } return 1;}
