问题:
写一个程序,让用户来决定Windows任务管理器(Task Manager)的CPU占用率(单核)。有以下几种情况:
1.CPU占用率固定在50%,为一条直线
2.CPU的占用率为一条直线,具体占用率由命令行参数决定(范围1~100)
3.CPU的占用率状态为一条正弦曲线
4.多核处理器情况下上述问题怎么解决
分析与解答
首先确定CPU占用率的定义,即在任务管理器的一个刷新周期内,CPU忙(执行应用程序)的时间和刷新周期总时间的比率,就是CPU的占用率,也可以说成,任务管理器中显示的是每个刷新周期内CPU占用率的统计平均值。所以可以写个程序,在一个刷新周期中,一会儿忙,一会儿闲,调节忙/闲比例,就可以控制CPU占有率了。
一个刷新时间是多久,书上说,通过对任务管理器观测,大约是1秒。鼠标移动、后台程序等都会对曲线造成影响!
单核环境下,空死循环会导致100%的CPU占用率。双核环境下,CPU总占用率大约为50%,四核是25%左右。
解法一:简单解法
Busy用可循环来实现,for(i=0;i<n;i++) ;对应的汇编语言为
loop;
mov dx i ;将i置入dx寄存器
inc dx ;将dx寄存器加1
mov dx i ;将dx中的值赋回i
cmp i n ;比较i和n
j1 loop ;i小于n时则重复循环
我的cpu是 I5 2410M 2.30GHZ(双核四线程,如图) 因为目前的cpu每个时钟周期可执行两条以上的代码,取平均值2,于是(2300000000*2)/5=920000000(循环/秒) 每秒可以执行循环920000000次。
不能简单的取n=920000000然后sleep(1000),如果让cpu工作1s,休息1s很可能是锯齿,先达到一个峰值然后跌入一个很低的占有率;所以我们睡眠时间改为100ms,100ms比较接近windows的调度时间,n=92000000。如果sleep时间选的太小,会造成线程频繁的唤醒和挂起,无形中增加了内核时间的不确定性因此代码如下:
#include <windows.h>
int main(void)
{
//Run on CPU 0(0x00000001)(00000001)
//Run on CPU 1(0x00000002)(00000010)
//Run on CPU 0 AND CPU 1(0x00000003)(00000101)
//Run on CPU 2(0x00000004)(00000100)
//......
//SetProcessAffinityMask(GetCurrentProcess(),0x1);//进程与指定cpu绑定
SetThreadAffinityMask(GetCurrentThread(), 0x1);//线程与指定cpu绑定
while(true)
{
for(int i=0;i<92000000;i++)
;
Sleep(100);
}
return 0;
}
使用SetProcessAffinityMask函数,进程与CPU绑定,得到如下图。