你的位置:首页 > 操作系统

[操作系统]玩转CPU运行曲线


Leaf

是不是从来没有想过看看cpu运行曲线啊骚年?顶多也就仅仅是看看cpu利用率,吓自己一跳后感觉关闭几个不该打开的程序~

然而问题来了,微软公司要让你绘制cpu运行曲线啊!!不仅是固定的直线,还要绝对值函数,还有正弦!!我的天这游戏还能玩?

Require

写一个程序,让用户来决定Windows任务管理器(Task Manager)的CPU占用率。程序越简越好,计算机语言不限。例如,可以实现下面三种情况:

  1. CPU的占用率固定在50%,为一条直线
  2. CPI的占用率为一条直线,但是具体占用率由命令行参数决定(参数范围1~100)
  3. CPU的占用率状态是一个正弦曲线

Analysis

若不小心写了一个死循环,CPU的占用率就会跳到最高,并且一直保持在100%。我们也可以打开任务管理器,实际观察一下它是怎样变动的。凭肉眼观察,它大约是1秒钟更新一次。一般情况下,CPU使用率会很低。但是当一个用户运行一个程序,执行一些复杂操作的时候,CPU的使用率会急剧升高。当用户晃动鼠标时,CPU的使用率也会有小幅度的变化。 

当任务管理器报告的CPU使用率为0的时候,谁在使用CPU呢?通过任务管理器的进程(Process)一栏可以看到,System Idle Process占用了CPU的空闲的时间。系统中有那么多进程,它们什么时候能“闲下来”呢?答案很简单,这些程序或在等待用户的输入,或在等待某些事件的发生,或者主动进入休眠状态。

在任务管理器的一个刷新周期内,CPU忙(执行应用程序)的时间和刷新周期总时间的比率,就是CPU的占用率,也就是说,任务管理器中显示的是每个刷新周期内CPU占用率的统计平均值。因此,我们可以写一个程序,让它在任务管理器的刷新期间内一会忙,一会闲,然后通过调节忙/闲的比例,就可以控制任务管理器中显示的CPU占用率。

Solution

此处提供4种解法

【解法一】简单的解法

通过Busy loop() ,Sleep()来操作CPU的使用率曲线

需要了解的知识 

http://blog.csdn.net/zhandoushi1982/article/details/6101515http://blog.csdn.net/phunxm/article/details/9013535 
#include <windows.h>int main(){  for ( ; ; )  {    for ( int i= 0; i < 4000000000; i++) // 循环次数由具体cpu决定      ;    Sleep(10); // 看上面网址里的内容哟~  }  return 0;}

 

 【解法二】使用GetTickCount(()和Sleep()

通俗易懂,没什么好解释的,不懂的话就绝望吧,绝望一会就OK了

 

#include <windows.h>int main(){  int busyTime = 10; // 10 ms   int idleTime = busyTime; // same ratio willlead to 50% cpu usage    _int64 startTime = 0,middleTime = 0;  while(true)  {    startTime = GetTickCount ();    // busy loop    while (((middleTime=GetTickCount ()) - startTime) <= busyTime)      ;        // idle loop    Sleep(idleTime);  }return 0;}

【解法三】能动态适应的算法

因为注释着C#,所以我就并不想去理它了。额,对了,它用了Microsoft.Net Framework 提供的PerformanceCounter对象,不懂就去百度吧~

 

static void MakeUsage(float level){  PerformanceCounter p = new PerformanceConter("Processor", "% ProcessorTime", "_Total");  while(true)  {    if(p.NextValue() > level)      Sysem.Threading.Thread.Sleep(10);  }}

 

【解法四】正弦曲线

好了,认真学完前三个的乖同学现在已经能编CPU的正弦曲线啦(不能的话我也帮不了你了。。原谅我括号里面打省略号。。)

现在直接上代码吧!!

 

#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];   // array of busy times  DWORD idleSpan[COUNT];   // array of idle times  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;  }  DWORD startTime = 0;  int j = 0;  while(true)  {    j = j % COUNT;    startTime = GetTickCount();    while((GetTickCount() - startTime) <= busySpan[j])      ;    Sleep(idleSpan[j]);    j++;  }  return 0;}

复制代码好玩吗?啊?哈哈哈,是不是觉得为什么我没有正弦曲线啊?这些方法并没有什么卵用,是不是这样觉得?其实是有用的,我不会告诉你的。有问题欢迎讨论

附上江湖代码一份

原址 

http://www.cnblogs.com/Ripper-Y/archive/2012/05/19/2508511.html 
#include <iostream>#include <cmath>#include <ctime>#include <windows.h>using namespace std;//得到循环0xFFFFFFFF次用的秒数unsigned int test(){  unsigned int c = 0xFFFFFFFF;  time_t t1, t2;  time(&t1);  for(unsigned int i = 0; i < c; i++)    ;  time(&t2);  return (unsigned int)(t2 -t1);}#define T 20000                    //周期时间 20秒#define C 100                      //采样点时间间隔#define PI 3.1415                    //PIconst unsigned int count = 0xFFFFFFFF / (test() *1000); //采样间隔可以执行的循环数目const unsigned int N = T/C;                //周期内采样点数目unsigned int v[N] = { 0 };                //所有采样点连续执行循环数unsigned int mt[N] = { 0 };                //所有采样点休眠毫秒数int main(){  //计算循环次数和休眠时间  for(int i = 0; i < N; i++)  {    double x = 2 * PI * i / N;    double r = (sin(x) + 1) / 2;        mt[i] = C - r * C;    v[i] = r * C * count;  }  for(;;)  {    for(int i = 0; i < N; i++)    {      for(int j = 0; j < v[i]; j++)        ;      Sleep(mt[i]);    }  }  return 0;}

 

Tree

第一节是关于硬件的知识,要学的东西真不少。对了,最近决定要学习Html+Css和数据加密所以我会非常忙!!其实我自己都不信。。好咯大概就是这么多咯,写着真累。整篇文章全手打,摘自编程之美~