相关文章推荐

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版本下均有对应指令可以获取,会方便许多,此处不贴代码。

整体可执行源码(还包含其他功能代码,跳过即可),稍后上传。

版权声明:本文为CSDN博主「qq_37885346」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接: https://blog.csdn.net/qq_37885346/article/details/105583729