首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

即時取得指定進程 CPU 使用率:NtQuerySystemInformation 實作

     編輯:VC 教學

原理

在取樣間隔內,計算目標進程核心+使用者時間總和佔所有進程總時間的比例。需呼叫未文件化的 NtQuerySystemInformation (SystemInformationClass=5) 取得 SYSTEM_PROCESS_INFORMATION 結構陣列。

關鍵結構定義

typedef struct _THREAD_INFO {
    LARGE_INTEGER CreateTime;
    DWORD dwUnknown1, dwStartAddress, StartEIP, dwOwnerPID, dwThreadId;
    DWORD dwCurrentPriority, dwBasePriority, dwContextSwitches, Unknown;
    DWORD WaitReason;
} THREADINFO;

typedef struct _PROCESS_INFO {
    DWORD dwOffset, dwThreadsCount, dwUnused1[6];
    LARGE_INTEGER CreateTime, UserTime, KernelTime;
    UNICODE_STRING ProcessName;
    DWORD dwBasePriority, dwProcessID, dwParentProcessId, dwHandleCount;
    DWORD dwUnused3[2], dwVirtualBytesPeak, dwVirtualBytes, dwPageFaults;
    DWORD dwWorkingSetPeak, dwWorkingSet;
    DWORD dwQuotaPeakPagedPoolUsage, dwQuotaPagedPoolUsage;
    DWORD dwQuotaPeakNonPagedPoolUsage, dwQuotaNonPagedPoolUsage;
    DWORD dwPageFileUsage, dwPageFileUsagePeak, dCommitCharge;
    THREADINFO ThreadSysInfo[1];
} PROCESSINFO;

核心函式

int GetProcessCpuUsage(int pid) {
    static __int64 LastTotal = 0, LastCur = 0;
    PVOID pBuf = new BYTE[0x20000];
    typedef LONG (__stdcall *PFN)(DWORD, PVOID, DWORD, DWORD);
    PFN NtQSI = (PFN)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");
    NtQSI(5, pBuf, 0x20000, 0);
    PPROCESSINFO p = (PPROCESSINFO)pBuf;
    __int64 Total = 0, Cur = 0;
    DWORD ws = 0;
    do {
        Total += p->KernelTime.QuadPart + p->UserTime.QuadPart;
        if (p->dwProcessID == (DWORD)pid) {
            ws = p->dwWorkingSet;
            Cur += p->KernelTime.QuadPart + p->UserTime.QuadPart;
        }
        if (p->dwOffset == 0) break;
        p = (PPROCESSINFO)((BYTE*)p + p->dwOffset);
    } while (true);
    int totalDelta = (int)(Total - LastTotal);
    int curDelta = (int)(Cur - LastCur);
    int cpu = (totalDelta != 0) ? (100 * curDelta / totalDelta) : 0;
    LastTotal = Total; LastCur = Cur;
    delete[] pBuf;
    return cpu;
}

主控台測試

int main() {
    while (true) {
        printf("%d\n", GetProcessCpuUsage(0)); // 0 = System Idle Process
        Sleep(1000);
    }
    return 0;
}

若需監控特定 PID,請替換參數。程式碼於 Win2000/XP 測試通過。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved