一、题目:写一个程序,让windows任务管理器中的CPU占用率显示为一条正弦函数曲线。
第一眼看到这个题目,本人确实是没有多大思路的。因为一直没有对性能和CPU占用上考虑太多。真正看书查资料弄完才觉得确实很不错的一个应用题。以下将一步步完成控制的任务。
二、本人运行环境:
操作系统:win 7 32位
CPU: intel i7 2630QM(2.0GHZ 4核8线程)
三、具体实现
1. 多CPU的解决办法
因为程序在多CPU下会效果显示混乱,所以需要代码来指定程序在哪个CPU下运行。
可以用Windows API来指定CPU,代码如下:
-
- SetProcessAffinityMask(
- GetCurrentProcess(),
- 0x00000001
- );
2. 控制CPU的思路
CPU有两种状态:忙、闲。
控制忙:死循环。
控制闲:睡眠。
Windows资源管理器:显示的CPU曲线是一条记录型的曲线,会记录CPU的当前的占用率,然后慢慢绘制成线。
3. 通过计算CPU频率来控制CPU
- #include <stdio.h>
- #include <stdlib.h>
- #include "windows.h"
-
- int main()
- {
-
- SetProcessAffinityMask(
- GetCurrentProcess(),
- 0x00000001
- );
-
- for(;;)
- {
-
-
-
- for(int i=0;i<8000000;i++)
- ;
- Sleep(10);
- }
-
-
- return 0;
- }
运行效果:
可以看出,效果不是很好。人工计算肯定是不准确的!而且其他程序也会占用CPU。
4. 通过GetTickCount()函数来设置时间间隔
这样做的好处就是不用估算CPU的频率了,较上面的方法肯定好多了。
- #include <stdio.h>
- #include <stdlib.h>
- #include "windows.h"
-
- int main()
- {
-
- SetProcessAffinityMask(
- GetCurrentProcess(),
- 0x00000001
- );
-
- int busyTime = 100;
- int idleTime = busyTime;
- int start = 0;
- while(true)
- {
-
- start = GetTickCount();
- while((GetTickCount() - start) <= busyTime)
- ;
-
- Sleep(idleTime);
- }
-
- return 0;
- }
效果:
当然效果也一般,为下面的做铺垫。
5. 画正弦函数
要想画出正弦函数曲线,CPU忙的时间必须是慢慢递增的,然后递减。而CPU闲的时间必须是慢慢递减然后递增。
这样就是一个周期。最后一直循环重复即得到正弦函数曲线。
一下打印出部分忙闲时间关系:
代码:
- #include <Windows.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
- #include <tchar.h>
-
- const double SPLIT = 0.01;
- const int COUNT = 200;
- const double PI = 3.14159265;
- const int INTERVAL = 300;
-
-
- int _tmain(int argc, _TCHAR* argv[])
- {
-
- SetProcessAffinityMask(
- GetCurrentProcess(),
- 0x00000001
- );
-
-
- 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));
- idleSpan[i] = INTERVAL - busySpan[i];
- radian += SPLIT;
- }
-
-
- FILE *fp;
- fp = fopen("result.txt", "a+");
- for(int i = 0; i < COUNT; i++)
- {
-
-
- fprintf(fp, "busySpan[%d] is %d\n" , i, busySpan[i]);
- fprintf(fp, "idleSpan[%d] is %d\n\n" , i , idleSpan[i]);
- }
- fclose(fp);
-
-
-
- DWORD startTime = 0;
- int j = 0;
- while (true)
- {
- j = j % COUNT;
- startTime = GetTickCount();
- while ((GetTickCount() - startTime) <= busySpan[j])
- ;
- Sleep(idleSpan[j]);
- j++;
- }
-
- return 0;
- }
运行效果:
改变间隔时间INTERVAL = 100; 时可以相应使周期减小:
参考《编程之美》与 互联网