问题:
用程序控制Windows任务管理器中的CPU占用率,包括以下三种情况:
1、固定在50%
2、固定在某一个值,这个值由用户决定
3、曲线是一条正弦曲线
分析:
首先来观察一下任务管理器,可以得到以下结论:
- 大约1秒钟更新一次CPU占用率
- 系统空闲的情况下,CPU占用率在5%以下,但是只要有轻微动作,包括鼠标移动,就会影响占用率
- CPU空闲时,一个叫System Idle Process的进程占用了CPU
在任务管理器的一个刷新周期内,CPU忙和空闲时间的比值就是占用率。这样,可以写一个程序,控制CPU忙的时间即可。而让CPU忙可以用循环解决(想想死循环时CPU就100%的情况),而空闲可以用Sleep解决
解法:
1、让CPU在周期内运行busy和idle两个循环,通过控制比例来控制占用率。这里关键是估算50%所需的循环量。这里要注意一个问题,在一秒钟的周期里,不能够一次性运行完循环,然后彻底休息。这样很容易造成锯齿状的忽高忽低现象。以下是问题一的Code:
2、解法一的问题在于估算的难度和不准确。解法二使用GetTickCount函数获取运行时间,然后让循环和空闲运行相等的时间即可。
3、解法二中的做法可以精确调整循环和空闲的比例,因此调整比例就可以做出正弦曲线。
4、解法三在单核CPU上运行良好,在多核CPU上可以使用GetCurrentProcess和SetProcessAffinityMask函数控制进程在制定CPU上运行。
以下是四个解法的Code:
// 解法1
int main()
{
for(;;)
{
for(int i = 0; i < 9600000; i++)
;
Sleep(10);
}
return 0;
}
// 解法2
int main()
{
int busyTime = 10; // 10ms
int idleTime = busyTime; // 50% Usage
long startTime = 0;
while(1)
{
startTime = GetTickCount();
while1;
idleSpan[i] = INTERVAL – busySpan[i];
radian += SPLIT;
}
DWORD startTime = 0;
int j = 0;
while(1)
{
j = j % COUNT;
startTime = GetTickCount();
while2;
24 idleSpan[i] = INTERVAL – busySpan[i];
25 radian += SPLIT;
26 }
27 DWORD startTime = 0;
28 int j = 0;
29 while (true)
30 {
31 j = j % COUNT;
32 startTime = GetTickCount();
33 while ((GetTickCount() – startTime) <= busySpan[j]) ;
34 Sleep(idleSpan[j]);
35 j++;
36 }
37 return 0;
38 }
呵呵,没事的时候钻研一下貌似感觉不错!
- GetTickCount() – startTime) <= busyTime)
;
Sleep(idleTime);
}
}
// 解法3
#include <windows.h>
#include <stdlib.h>
#include <math.h>
const double SPLIT = 0.01;
const int COUNT = 200;
const double PI = 3.14159265;
const int INTERVAL = 300;
int main()
{
DWORD busySpan[COUNT];
DWORD idleSpan[COUNT];
int half = INTERVAL / 2;
double radian = 0.0;
for(int i = 0; i < COUNT; i++)
{
busySpan[i] = (DWORD)(half + (sin(PI * radian) * half [↩] - GetTickCount() – startTime) <= busySpan[j])
;
Sleep(idleSpan[j]);
j++;
}
return 0;
}解法四
1 #include “Windows.h”
2 #include “stdlib.h”
3 #include “math.h”
4
5 const double SPLIT = 0.01;
6 const int COUNT = 200;
7 const double PI = 3.14159265;
8 const int INTERVAL = 300;
9
10 int _tmain(int argc, _TCHAR* argv[])
11 {
12 SetProcessAffinityMask(
13 GetCurrentProcess(),
14 0×00000001 //cpu mask
15 );
16
17 DWORD busySpan[COUNT]; //array of busy times
18 DWORD idleSpan[COUNT]; //array of idle times
19 int half = INTERVAL / 2;
20 double radian = 0.0;
21 for(int i = 0; i < COUNT; i++)
22 {
23 busySpan[i] = (DWORD)(half + (sin(PI * radian) * half [↩]