#include <iostream>
#include <iomanip>
#include <windows.h>
using namespace std;

int CompareFileTime(FILETIME time1, FILETIME time2)
{
	int a = time1.dwHighDateTime << 32 | time1.dwLowDateTime ;
	int b = time2.dwHighDateTime << 32 | time2.dwLowDateTime ;
	return (b - a);
}//原文用的是_int64类型,但是我的电脑是32位Windows系统,安全考虑用int
//这个函数这样写到底对不对,还需要商榷。即使是原文,后面调用这个函数时,
//左值也是int型的,所以_int64肯定有问题。那么改成int后这个算法要推敲。 

int main(){
	FILETIME idleTime;
	FILETIME kernelTime;
	FILETIME userTime;
	bool res;
	res = GetSystemTimes(&idleTime, &kernelTime, &userTime);
	cout << "res = " << res << endl;
	
	HANDLE hEvent;
	FILETIME pre_idleTime;
	FILETIME pre_kernelTime;
	FILETIME pre_userTime;
	
	pre_idleTime = idleTime;
	pre_kernelTime = kernelTime;
	pre_userTime = userTime;
	
	hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 
	// 初始值为 nonsignaled ,并且每次触发后自动设置为nonsignaled
	
	while (1){
		WaitForSingleObject( hEvent,1000 ); //等待500毫秒
		
		res = GetSystemTimes(&idleTime, &kernelTime, &userTime );
     
		int idle = CompareFileTime(pre_idleTime,idleTime);
		int kernel = CompareFileTime(pre_kernelTime, kernelTime);
		int user = CompareFileTime(pre_userTime, userTime);

		int cpu_occupancy_rate = (kernel + user - idle) * 100 / (kernel+user);
		//(总的时间 - 空闲时间)/ 总的时间 = 占用cpu的时间,也就是占用率
		
		int cpu_idle_rate = (-idle) * 100 / (kernel + user);
		//应该是正值还是负值? 
		
		cout << left << setw(10) << "CPU占用率:" << cpu_occupancy_rate << "%" << endl
			<< setw(10) << "CPU闲置率:" << cpu_idle_rate << "%" << endl << endl;

		pre_idleTime = idleTime;
		pre_kernelTime = kernelTime;
		pre_userTime = userTime;
    }
	
	return 0;
}


测试结果虽然是CLI界面,但是是动态推进的:

gettimes转时间 getsystemtimes_gettimes转时间

这个代码中有不少技术亮点,值得好好研究。

编译器的警告提示:

gettimes转时间 getsystemtimes_Time_02

加上运行结果中CPU占用率与闲置率的和并不是100%,而且我还在局部变量idle前面加了一个负号,才让两个比率都是正值——所以我有理由怀疑:这个网上拷来的代码其实是错的!如何修改,待后期研究。

=============================== 菜鸟的分割线 =================================

菜鸟啊菜鸟!我的确是菜鸟!T_T!今天9月5日上午经过仔细研究后,发现FILETIME结构体的两个成员到底是什么意思了!原来是两个双字节数拼起来表示时间的,一个双字节是高32位,另一个是低32位,最终拼在一起表示一个64位字长的文件时间变量!所以用__int64(注意前面必须有连续的两条下划线)作为CompareFiletime函数的参数类型和返回类型,都是对的!另外GetSystemTimes的三个参数,一个是闲置时间,一个是核心态时间,一个是用户态时间。可以在算出CPU占用率和闲置率的同时,还算出核心态占用比率、用户态占用比率!这样对CPU的负载监视更加清楚、精确!修改后的代码如下:

#include <iostream>
#include <iomanip>
#include <windows.h>
using namespace std;

__int64 CompareFileTime(FILETIME time1, FILETIME time2)
{
	__int64 a = time1.dwHighDateTime << 32 | time1.dwLowDateTime ;
	__int64 b = time2.dwHighDateTime << 32 | time2.dwLowDateTime ;
	return (b - a);
}//经过对FILETIME structure的两个参数的研究,发现用__int64类型是对的! 
//只要操作正确,__int64类型数据也不会导致在32位系统上出现不安全的错误。 

int main(){
	FILETIME idleTime;//空闲时间 
	FILETIME kernelTime;//核心态时间 
	FILETIME userTime;//用户态时间 
	bool res;
	res = GetSystemTimes(&idleTime, &kernelTime, &userTime);
	cout << "GetSystemTimes(&, &, &) = " << res << endl << endl;
	
	HANDLE hEvent;
	FILETIME pre_idleTime;
	FILETIME pre_kernelTime;
	FILETIME pre_userTime;
	
	pre_idleTime = idleTime;
	pre_kernelTime = kernelTime;
	pre_userTime = userTime;
	
	hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 
	//初始值为nonsignaled,并且每次触发后自动设置为nonsignaled
	
	while (1){
		WaitForSingleObject( hEvent,1000 );//等待500毫秒
		
		res = GetSystemTimes(&idleTime, &kernelTime, &userTime );
     
		__int64 idle = CompareFileTime(pre_idleTime, idleTime);
		__int64 kernel = CompareFileTime(pre_kernelTime, kernelTime);
		__int64 user = CompareFileTime(pre_userTime, userTime);

		int cpu_occupancy_rate = (kernel + user - idle) * 100 / (kernel + user);
		//(总的时间 - 空闲时间)/ 总的时间 = 占用CPU时间的比率,即占用率
		
		int cpu_idle_rate = idle * 100 / (kernel + user);
		//空闲时间 / 总的时间 = 闲置CPU时间的比率,即闲置率 
		
		int cpu_kernel_rate = kernel * 100 / (kernel + user);
		//核心态时间 / 总的时间 = 核心态占用的比率 
		
		int cpu_user_rate = user * 100 / (kernel + user);
		//用户态时间 / 总的时间 = 用户态占用的比率 
		
		cout << left << setw(15) << "CPU占用率:" << cpu_occupancy_rate << "%" << endl
			<< setw(15) << "CPU闲置率:" << cpu_idle_rate << "%" << endl
			<< setw(15) << "核心态占比率:" << cpu_kernel_rate << "%" << endl
			<< setw(15) << "用户态占比率:" << cpu_user_rate << "%" << endl << endl;

		pre_idleTime = idleTime;
		pre_kernelTime = kernelTime;
		pre_userTime = userTime;
    }
	
	return 0;
}


gettimes转时间 getsystemtimes_gettimes转时间_03


当打开某个程序时,比如开一个网页,核心态占比率会迅速下降,同时用户态占比率迅速上升。截图中第5段、第6段数据显示的就是我打开一个网页时,CPU文件时间的变化情况,不仅CPU占用率迅速上升,而且用户态占比率也迅速上升。在第7段数据时,CPU占比率和用户态占比率同时下降,这个时间只用了2 * 500ms = 1s。

第6章负载监视器设计的第一个底层接口:CPU占用率的获得宣告搞定!