有趣的编程----控制自己电脑的CPU

一、题目写一个程序,让windows任务管理器中的CPU占用率显示为一条正弦函数曲线

第一眼看到这个题目,本人确实是没有多大思路的。因为一直没有对性能和CPU占用上考虑太多。真正看书查资料弄完才觉得确实很不错的一个应用题。以下将一步步完成控制的任务。

二、本人运行环境:

操作系统:win 7 32位
CPU: intel i7 2630QM(2.0GHZ 4核8线程)

三、具体实现

1.  多CPU的解决办法


因为程序在多CPU下会效果显示混乱,所以需要代码来指定程序在哪个CPU下运行。
可以用Windows API来指定CPU,代码如下:
[cpp]  view plain  copy
  1. //让进程在指定处理器上运行(在第一个CPU上运行, 对多CPU的处理)  
  2.     SetProcessAffinityMask(  
  3.         GetCurrentProcess(),  
  4.         0x00000001          //cpu mask  
  5.          );  

2. 控制CPU的思路


CPU有两种状态:
控制死循环
控制睡眠
Windows资源管理器:显示的CPU曲线是一条记录型的曲线,会记录CPU的当前的占用率,然后慢慢绘制成线。

3. 通过计算CPU频率来控制CPU

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include "windows.h"  
  4. //控制CPU , 需要计算CPU运行时间   
  5. int main()  
  6. {  
  7.     //让进程在指定处理器上运行(在第一个CPU上运行, 对多CPU的处理)  
  8.     SetProcessAffinityMask(  
  9.         GetCurrentProcess(),  
  10.         0x00000001          //cpu mask  
  11.          );  
  12.       
  13.     for(;;)  
  14.     {  
  15.         //CPU 2.0GHZ  4核心 8线程  
  16.         //计算方法: 2.0*10的9次方 , 现代CPU每个时钟周期可以执行2条以上的代码  
  17.         //2000 000 000*2/5=800 000 000 平均   
  18.         for(int i=0;i<8000000;i++)  
  19.         ;  
  20.         Sleep(10);//10ms比较接近windows的调度时间片   
  21.     }  
  22.       
  23.     //system("PAUSE");  
  24.     return 0;  
  25. }  
运行效果:


可以看出,效果不是很好。人工计算肯定是不准确的!而且其他程序也会占用CPU。

4. 通过GetTickCount()函数来设置时间间隔


这样做的好处就是不用估算CPU的频率了,较上面的方法肯定好多了。

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include "windows.h"  
  4. //控制CPU  
  5. int main()  
  6. {  
  7.     //让进程在指定处理器上运行(在第一个CPU上运行, 对多CPU的处理)  
  8.     SetProcessAffinityMask(  
  9.         GetCurrentProcess(),  
  10.         0x00000001          //cpu mask  
  11.          );  
  12.   
  13.     int busyTime = 100;  
  14.     int idleTime = busyTime;  
  15.     int start = 0;  
  16.     while(true)  
  17.     {  
  18.         //用系统函数省去了CPU运行时间的估算   
  19.         start = GetTickCount();  
  20.         while((GetTickCount() - start) <= busyTime)  
  21.         ;  
  22.         //空闲   
  23.         Sleep(idleTime);   
  24.     }   
  25.     //system("PAUSE");  
  26.     return 0;  
  27. }  
效果:


当然效果也一般,为下面的做铺垫。

5. 画正弦函数


要想画出正弦函数曲线,CPU忙的时间必须是慢慢递增的,然后递减。而CPU闲的时间必须是慢慢递减然后递增。

这样就是一个周期。最后一直循环重复即得到正弦函数曲线。

一下打印出部分忙闲时间关系:



代码:
[cpp]  view plain  copy
  1. #include <Windows.h>  
  2. #include <stdlib.h>  
  3. #include <stdio.h>  
  4. #include <math.h>   
  5. #include <tchar.h>  
  6.   
  7. const double SPLIT = 0.01;  
  8. const int COUNT = 200;   
  9. const double PI = 3.14159265;  
  10. const int INTERVAL = 300;   //间隔时间   
  11.   
  12. //画出一条正弦曲线  
  13. int _tmain(int argc, _TCHAR* argv[])  
  14. {  
  15.     //让进程在指定处理器上运行(在第一个CPU上运行, 对多CPU的处理)  
  16.     SetProcessAffinityMask(  
  17.         GetCurrentProcess(),  
  18.         0x00000001          //cpu mask  
  19.          );  
  20.   
  21.     //1. 设置忙与闲时的时间数组   
  22.     DWORD busySpan[COUNT];  //array of busy times  
  23.     DWORD idleSpan[COUNT];  //array of idle times  
  24.     int half = INTERVAL / 2;  
  25.     double radian = 0.0;   //弧度   
  26.     for(int i = 0; i < COUNT; i++)  
  27.     {  
  28.         //sin(x)的取值范围是[-1,1],为了完整显示,必须给它作些参数调整  
  29.         busySpan[i] = (DWORD)(half + (sin(PI * radian) * half));  
  30.         idleSpan[i] = INTERVAL - busySpan[i];  
  31.         radian += SPLIT; //每次增一点点   
  32.     }  
  33.       
  34.     //测试:输出忙与闲时的时间数组, 写入文件result.txt  
  35.     FILE *fp;                    
  36.     fp = fopen("result.txt""a+");    //a+表示追加方式  
  37.     for(int i = 0; i < COUNT; i++)  
  38.     {  
  39.        //printf("busySpan[%d] is %d\n",i,busySpan[i]);  
  40.        //printf("idleSpan[%d] is %d\n\n",i,idleSpan[i]);  
  41.         fprintf(fp, "busySpan[%d] is %d\n" , i, busySpan[i]);    
  42.         fprintf(fp, "idleSpan[%d] is %d\n\n" , i , idleSpan[i]);                      
  43.     }  
  44.     fclose(fp);  
  45.       
  46.   
  47.     //2. 画曲线   
  48.     DWORD startTime = 0;          
  49.     int j = 0;  
  50.     while (true)  
  51.     {  
  52.         j = j % COUNT;    //COUNT次为一个周期   
  53.         startTime = GetTickCount();  
  54.         while ((GetTickCount() - startTime) <= busySpan[j])  
  55.         ;  
  56.         Sleep(idleSpan[j]);  
  57.         j++;  
  58.     }  
  59.       
  60.     return 0;  
  61. }  

运行效果:


改变间隔时间INTERVAL = 100; 时可以相应使周期减小:





转载请注明出处:http://blog.csdn.net/xn4545945  

参考《编程之美》与 互联网
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值