1、获取系统cpu:
使用WindowsAPI函数GetSystemTimes(),为获取当前使用率,通过执行两次的方式进行差值比较。在win7,win10上试验结果准确,具体用法参考下列代码:
//Windows程序获取cpu占用率
void GetCpuUsage_WIN(double* CPUResult) {
CPUResult[0] = 0;
CPUResult[1] = 0;
FILETIME ftIdle, ftKernel, ftUser;
//GetSystemTimes()获取系统CPU空闲时间、内核时间、用户时间
if (GetSystemTimes(&ftIdle, &ftKernel, &ftUser)) {
m_fOldCPUIdleTime = FileTimeToDouble(&ftIdle);
m_fOldCPUKernelTime = FileTimeToDouble(&ftKernel);
m_fOldCPUUserTime = FileTimeToDouble(&ftUser);
//printf("自开机来的平均CPU占用率:%2.f%%", 100 * (1 - (m_fOldCPUIdleTime) / (m_fOldCPUKernelTime + m_fOldCPUUserTime)));
//printf(" %2.f%%\n", 100 * (m_fOldCPUIdleTime) / (m_fOldCPUKernelTime + m_fOldCPUUserTime));
Sleep(1000);
if (GetSystemTimes(&ftIdle, &ftKernel, &ftUser)) {
m_fOldCPUIdleTime = FileTimeToDouble(&ftIdle) - m_fOldCPUIdleTime;
m_fOldCPUKernelTime = FileTimeToDouble(&ftKernel) - m_fOldCPUKernelTime;
m_fOldCPUUserTime = FileTimeToDouble(&ftUser) - m_fOldCPUUserTime;
*计算cpu占用率,注意内核时间中包含空闲时间,空闲时间为cpu空转时间
*运行时间=用户时间+内核时间-空闲时间
*间隔时间=用户时间+内核时间
*cpu占用率=运行时间/间隔时间,cpu闲置率=空闲时间/间隔时间
*CPUResult++ = 100 * (1 - (m_fOldCPUIdleTime) / (m_fOldCPUKernelTime + m_fOldCPUUserTime));
*CPUResult = (m_fOldCPUIdleTime) / (m_fOldCPUKernelTime + m_fOldCPUUserTime) * 100;
CPUResult--;
win7比较如下:
2、获取进程CPU:
在最开始选择了使用GetProcessTimes()函数实现,发现其返回值中仅包含了内核时间以及用户时间,即使求取了差值也不清楚分母的大小,故在试验中使用GetSystemTimes()计算总时间。各位看官如可以采取更好的方式实现,可以在下发留言以供其他同学参考。
实现代码如下,win7、win10下与任务管理器结果一致,需注意,代码粗暴,自行优美:
//Windows执行cmd指令
bool Wincmd(char* cmd, char* result)
char buffer[128];//缓冲区
FILE* pipe = _popen(cmd, "r");//_popen函数创建管道调用fork产生子进程,以执行cmd指令,这个进程需以_pclose关闭
if (!pipe) {
_pclose(pipe);
return false;
while (!feof(pipe)) { //feof判断流、文件是否读完
if (fgets(buffer, 128, pipe)) {
strcat_s(result, 1024, buffer);
if (strlen(result) > 896) {
break;
_pclose(pipe);
return true;
//判断进程是否存在
bool IsProExit(int ID) {
char str[128] = "tasklist /FI \"PID eq ";
char strPID[24] = { '\0' };
char* strbuf = NULL;
char* tmpstr = NULL;
_itoa_s(ID, strPID, 24, 10);
strcat_s(str, strPID);
strcat_s(str, "\"\n");
Wincmd(str, result);
if (!strstr(result, "PID")) {
return false;
//获取PID进程名称
strtok_s(result, "\n", &strbuf);
strtok_s(strbuf, "\n", &tmpstr);
strtok_s(tmpstr, " ", &strbuf);
strncpy_s(ProName, tmpstr, strlen(tmpstr));
memset(result, '\0', sizeof(result));
return true;
//获取进程cpu占用率
void GetCpuUsagPID_WIN(double* CPUResult) {
CPUResult[0] = 0;
CPUResult[1] = 0;
if (PID <= 0) {
return;
//先判断进程是否存在
if (!IsProExit(PID)) {
CPUResult[0] = -1;//不存在则置为-1
return;
FILETIME ftCreate, ftExit, ftKernel_PID, ftUser_PID;
//GetProcessTimes()获取PID进程CPU空闲时间、内核时间、用户时间,单位是100ns
HANDLE hprocess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
if (GetProcessTimes(hprocess, &ftCreate, &ftExit, &ftKernel_PID, &ftUser_PID)) {
m_fOldCPUKernelTime_PID = (long long int)FileTimeToDouble(&ftKernel_PID);
//printf("m_fOldCPUKernelTime_PID:%lld \n" , m_fOldCPUKernelTime_PID);
m_fOldCPUUserTime_PID = (long long int)FileTimeToDouble(&ftUser_PID);
//printf("m_fOldCPUUserTime_PID:%lld \n", m_fOldCPUUserTime_PID);
FILETIME ftIdle, ftKernel, ftUser;
//GetSystemTimes()获取系统CPU空闲时间、内核时间、用户时间,单位:100ns
if (GetSystemTimes(&ftIdle, &ftKernel, &ftUser)) {
m_fOldCPUKernelTime = (long long int)FileTimeToDouble(&ftKernel);
//printf("m_fOldCPUKernelTime:%lld \n", m_fOldCPUKernelTime);
m_fOldCPUUserTime = (long long int)FileTimeToDouble(&ftUser);
//printf("m_fOldCPUUserTime:%lld \n", m_fOldCPUUserTime);
Sleep(1000);
if (GetProcessTimes(hprocess, &ftCreate, &ftExit, &ftKernel_PID, &ftUser_PID)) {
//printf("FileTimeToDouble(&ftKernel_PID):%lld \n", (long long int)FileTimeToDouble(&ftKernel_PID));
m_fOldCPUKernelTime_PID = (long long int)FileTimeToDouble(&ftKernel_PID) - m_fOldCPUKernelTime_PID;
//printf("m_fOldCPUKernelTime_PID:%lld \n", m_fOldCPUKernelTime_PID);
//printf("FileTimeToDouble(&ftUser_PID):%lld \n", (long long int)FileTimeToDouble(&ftUser_PID));
m_fOldCPUUserTime_PID = (long long int)FileTimeToDouble(&ftUser_PID) - m_fOldCPUUserTime_PID;
//printf("m_fOldCPUUserTime_PID:%lld \n", (long long int)m_fOldCPUUserTime_PID);
if (GetSystemTimes(&ftIdle, &ftKernel, &ftUser)) {
m_fOldCPUKernelTime = (long long int)FileTimeToDouble(&ftKernel) - m_fOldCPUKernelTime;
//printf("FileTimeToDouble(&ftKernel):%lld \n", (long long int) FileTimeToDouble(&ftKernel));
//printf("m_fOldCPUKernelTime:%lld \n", m_fOldCPUKernelTime);
m_fOldCPUUserTime = (long long int)FileTimeToDouble(&ftUser) - m_fOldCPUUserTime;
//printf("FileTimeToDouble(&ftUser):%lld \n", (long long int)FileTimeToDouble(&ftUser));
//printf("m_fOldCPUUserTime:%lld \n", m_fOldCPUUserTime);
else {
CPUResult[0] = 0;
CPUResult[1] = 0;
return;
*进程当前cpu占用率=(进程内核时间增量+进程用户时间增量)/(系统内核时间增量+系统用户时间增量)
//printf("%.7f\n", m_fOldCPUKernelTime + m_fOldCPUUserTime);
CPUResult[0] = (double)(m_fOldCPUKernelTime_PID + m_fOldCPUUserTime_PID)*100 / (double)(m_fOldCPUKernelTime + m_fOldCPUUserTime);
win7试验结果如下;
3、系统内存:
GlobalMemoryStatusEx()函数,代码不展示了,获取对应属性值就行。
4、进程内存:
最开始打算:
GlobalMemoryStatusEx()获取系统总内存;
GetProcessMemoryInfo()获取进程内存;
完成后发现误差极大,基本上实验中数据均偏大50%以上,由于试验最开始在win7上进行,考虑版本问题。
经过搜索发现博主v2x222的这篇博客:
https://blog.csdn.net/v2x222/article/details/51784569
,解决了这个问题。
故此节代码改自其代码;
void GetMemVerOld(int* PIDMem) {
SYSTEM_INFO si;
GetSystemInfo(&si);
PSAPI_WORKING_SET_INFORMATION workSet;
HANDLE hprocess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
memset(&workSet, 0, sizeof(workSet));
BOOL bOk = QueryWorkingSet(hprocess, &workSet, sizeof(workSet));
if (bOk || (!bOk && GetLastError() == ERROR_BAD_LENGTH))
int nSize = sizeof(workSet.NumberOfEntries) + workSet.NumberOfEntries*sizeof(workSet.WorkingSetInfo);
char* pBuf = new char[nSize];
if (pBuf)
QueryWorkingSet(hprocess, pBuf, nSize);
PSAPI_WORKING_SET_BLOCK* pFirst = (PSAPI_WORKING_SET_BLOCK*)(pBuf + sizeof(workSet.NumberOfEntries));
DWORD dwMem = 0;
for (ULONG_PTR nMemEntryCnt = 0; nMemEntryCnt < workSet.NumberOfEntries; nMemEntryCnt++, pFirst++)
if (pFirst->Shared == 0) dwMem += si.dwPageSize;
PIDMem[1] = dwMem / 1024;
printf("dwMem:%u\n", dwMem/1024);
//free(pBuf);
//free(hprocess);
void GetMemUsagPID_WIN(int* PIDMem) {
//先判断进程是否存在
if (!IsProExit(PID)) {
PIDMem[0] = -1;//不存在则置为-1
return;
//获取总内存大小,MB
GlobalMemoryStatusEx(&MemStat);
PIDMem[0] = MemStat.ullTotalPhys / 1024 / 1024;
//获取系统版本
OSVERSIONINFO osvi;
memset(&osvi, 0, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionExA(&osvi);//获取版本信息,需注意,windows8.1后 此函数被废弃,均返回6.2
//较旧版本
if (osvi.dwMajorVersion < 6.3){
GetMemVerOld(PIDMem);
return;
//较新版本
//GetProcessMemoryInfo()获取PID进程内存占用/字节
HANDLE hprocess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
if (GetProcessMemoryInfo(hprocess, &pmc, sizeof(pmc))) {
PIDMem[1] = pmc.WorkingSetSize / 1024;
PIDMem[2] = pmc.PagefileUsage / 1024 ;
else {
PIDMem[0] = -1;
return;
此时结果就十分精确了,只是kb级别(任务管理器显示为kb)是无误差的。
5、CPU、磁盘、网卡:
查阅对应API属实花了不少时间,最后考虑使用WMI API函数实现,另附赠磁盘IO。具体代码如下:
void UseWmi(int caseNum){
//result code from COM calls
HRESULT hr = 0;
//COM interface pointers
IWbemLocator *locator = NULL;
IWbemServices *services = NULL;
IEnumWbemClassObject *results = NULL;
BSTR resource = SysAllocString(L"ROOT\\CIMV2");
BSTR language = SysAllocString(L"WQL");
Win32_PerfFormattedData_PerfDisk_LogicalDisk 代表逻辑磁盘性能数据对象,利用该对象可以获得磁盘的心能信息。Win32_PerfFormattedData_PerfDisk_LogicalDisk对象有以下一些主要的属性:
Name: 磁盘名称
DiskTransfersPerSec:每秒磁盘传输次数。
DiskReadBytesPerSec:每秒从磁盘读取得数据量,单位为Byte。
DiskWriteBytesPerSec:每秒从磁盘读取得数据量,单位为Byte。
PercentFreeSpace:可用磁盘百分比。*/
BSTR query = NULL;
//设定query
switch (caseNum)
case 1:
query = SysAllocString(L"Select * FROM Win32_PerfFormattedData_PerfOS_Processor");
break;
case 3:
query = SysAllocString(L"Select * FROM Win32_PerfFormattedData_PerfDisk_LogicalDisk");
break;
case 30:
query = SysAllocString(L"Select * FROM Win32_PerfFormattedData_PerfProc_Process");
break;
case 4:
query = SysAllocString(L"Select * FROM Win32_PerfFormattedData_Tcpip_NetworkInterface");
break;
default:
break;
//BSTR query = SysAllocString(L"Select PercentProcessorTime,IDProcess from Win32_PerfFormattedData_PerfProc_Process where IDProcess=992");
//initialize COM
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
// connect to WMI
hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&locator);
hr = locator->ConnectServer(resource, NULL, NULL, NULL, 0, NULL, NULL, &services);
// issue a WMI query
hr = services->ExecQuery(language, query, WBEM_FLAG_BIDIRECTIONAL, NULL, &results);
// list the query results
if (results != NULL) {
IWbemClassObject *result = NULL;
ULONG returnedCount = 0;
// enumerate the retrieved objects
switch (caseNum)
case 1:
while ((hr = results->Next(WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
VARIANT name;
VARIANT PercentIdleTime;
// obtain the desired properties of the next result and print them out
hr = result->Get(L"Name", 0, &name, 0, 0);
//hr = result->Get(L"PercentIdleTime", 0, &PercentIdleTime, 0, 0);
hr = result->Get(L"PercentProcessorTime", 0, &PercentIdleTime, 0, 0);
BSTR tmp=PercentIdleTime.bstrVal;
wprintf(L"## CPU:%s\t\tUse:%s%%\r\n", name.bstrVal, PercentIdleTime.bstrVal);
if (EXCEL_status > 0) {
// release the current result object
result->Release();
break;
case 3:
DiskNum = 0;
while ((hr = results->Next(WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
// obtain the desired properties of the next result and print them out
hr = result->Get(L"Name", 0, &name[DiskNum + DiskDt], 0, 0);
hr = result->Get(L"DiskReadBytesPerSec", 0, &Readspeed[DiskNum + DiskDt], 0, 0);
hr = result->Get(L"DiskWriteBytesPerSec", 0, &Writespeed[DiskNum + DiskDt], 0, 0);
//wprintf(L"## DISK:%s\t\tReadSpeed:%d Bytes/s\t\tWriteSpeed:%d Byte/s,\r\n", name[DiskNum + DiskDt].bstrVal, Readspeed[DiskNum + DiskDt].intVal, Writespeed[DiskNum + DiskDt].intVal);
// release the current result object
result->Release();
DiskNum++;
break;
case 30:
while ((hr = results->Next(WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
VARIANT name;
char tmpID[256] = { '\0' };
// obtain the desired properties of the next result and print them out
hr = result->Get(L"IDProcess", 0, &name, 0, 0);
if (name.intVal == PID){
hr = result->Get(L"IODataBytesPersec", 0, &IODataBytesPersec, 0, 0);
hr = result->Get(L"IOReadBytesPersec", 0, &IOReadBytesPersec, 0, 0);
hr = result->Get(L"IOWriteBytesPersec", 0, &IOWriteBytesPersec, 0, 0);
//wprintf(L"## PID:%d\tTotalIOSpeed:%d Bytes/s\tReadIOSpeed:%d Byte/s,\tWriteIOSpeed:%d Byte/s,\r\n", PID, IODataBytesPersec.intVal, IOReadBytesPersec.intVal, IOWriteBytesPersec.intVal);
// release the current result object
result->Release();
break;
case 4:
DiskNum = 0;//此处指代网卡数量,少定义变量,同样的还有DiskDt
while ((hr = results->Next(WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
//VARIANT name;
// obtain the desired properties of the next result and print them out
hr = result->Get(L"Name", 0, &name[DiskNum+DiskDt], 0, 0);
hr = result->Get(L"BytesReceivedPersec", 0, &BytesReceivedPersec[DiskNum + DiskDt], 0, 0);
hr = result->Get(L"BytesSentPersec", 0, &BytesSentPersec[DiskNum + DiskDt], 0, 0);
hr = result->Get(L"BytesTotalPersec", 0, &BytesTotalPersec[DiskNum + DiskDt], 0, 0);
//wprintf(L"## NETCARD:%s\n\tReceiveSpeed:%d Bytes/s\t\tSendSpeed:%d Bytes/s\t\tTotalSpeed:%d Bytes/s\r\n", name[DiskNum + DiskDt].bstrVal, BytesReceivedPersec[DiskNum + DiskDt].intVal, BytesSentPersec[DiskNum + DiskDt].intVal, BytesTotalPersec[DiskNum + DiskDt].intVal);
// release the current result object
result->Release();
DiskNum++;
break;
default:
break;
// release WMI COM interfaces
results->Release();
services->Release();
locator->Release();
// unwind everything else we've allocated
CoUninitialize();
SysFreeString(query);
SysFreeString(language);
SysFreeString(resource);
以上代码均可执行。
linux版本下均有对应指令可以获取,会方便许多,此处不贴代码。
整体可执行源码(还包含其他功能代码,跳过即可),稍后上传。