每个进程的CPU使用率

时间:2017-01-28 23:34:15

标签: c++ windows cpu-usage

我在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?

1 个答案:

答案 0 :(得分:1)

好的,要有效编码此任务,需要将NtQueryInformationProcessSystemProcessInformation信息类一起使用。我们在这里获得SYSTEM_PROCESS_INFORMATION数组。我们已经在这里:

LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;

PROCESSENTRY32时没有这个成员。 toolhelp函数只是删除此成员。如果没有它,我们需要打开每个流程,使用NtQueryInformationProcess调用GetProcessTimes等等都会变得更加有效和简单。一般的想法 - 我们需要维护进程列表,并定期调用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->KernelTime.QuadPart += pspi->UserTime.QuadPart;
        _Delta.QuadPart = pspi->KernelTime.QuadPart - _RunTime.QuadPart;
        _RunTime.QuadPart = pspi->KernelTime.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);
}