内容同样来自《编程之美》的第一节《让CPU曲线听你的指挥》,感觉我写的不清楚的可以移步《编程之美》这本书,优快云书库里面有,淘宝上有正版的,24元不过邮费10块,有一家淘宝包邮,也是正版的,不过书是书店图书馆下架的展示书.....
这一章里,总共有三个问题:
1.CPU的占用率固定在50%。
2.CPU的占用率为一条直线,具体占用率由命令行参数决定。
3.CPU的占用率状态是一条正弦曲线。
下面的东西只涉及到1,3问,第2问我也不会......
首先,我们先思考一个问题,CPU的占用率代表着什么?这个问题我们要在正在学习的操作系统里面寻找答案,在任务管理器的一个刷新周期内,CPU的执行应用程序事件和刷新周期总时间比就是CPU的占用率,知道了这个,我们就可以写一个程序,控制CPU在一个刷新周期内一会儿忙,一会儿闲,之后调节这个比例,保持在50%。
首先,我们将这个问题简化一下,让CPU是单核的,并且已近知道了CPU的频率,可以估算出一秒内CPU可以执行多少条指令,之后取一半,再考虑一下时间间隔,如果我们让CPU工作1秒,休息1秒,很容易出现一个起伏很大的波形,所以,回想一下windows系统课上老师说的windows调度时间片时间,10毫秒。
代码:
int main()
{
for (;;)
{
for (int i = 0; i < time; i++);
Sleep(10);
}
return 0;
}
这样,一个CPU直线出现了。
但是,有个问题,就是不同电脑怎么办,双核又怎么办。
还记得windows下有个函数么?GetTickCount(),这个是显示从系统启动到现在经历的时间,毫秒单位,有了它,我们就能判断我们的空循环需要多久了。
const DWORD busyTime = 10;
const DWORD int idleTime = busyTime;
Int64 startTime = 0;
while (true)
{
DWORD startTime = GetTickCount();
while (GetTickCount() - startTime <= busyTime);
Sleep(idleTime);
}
这样,画正弦曲线也不难了。
我们把正弦曲线0~2π之间的弧度等分200份,计算每个点振幅,然后每隔300ms的时间抽取下个点,并让CPU工作对应振幅的时间。
#include "windows.h"
#include "stdio.h"
#include "math.h"
const int SAMPLING_COUNT = 200;
const double PI = 3.1415926535;
const int TOTAL_AMPLITUDE = 300;
int _tmain(int argc, _TCHAR* argv[])
{
DWORD buySpan[SAMPLING_COUNT];
int amplintude = TOTAL_AMPLITUDE / 2;
double radian = 0.0;
double radianIncrement = 2.0 / (double)SAMPLING_COUNT;
for (int i = 0; i < SAMPLING_COUNT; ++i)
{
busySpan[i] = (DWORD)(amplitude + (sin(PI * radian) * amplitude));
radian += radianIncrement;
}
DWORD startTime = 0;
for (int j = 0;; j = (j + 1) % SAMPLING_COUNT)
{
startTime = GetTickCount();
while ((GetTickCount() - startTime) <= busySpan[j]);
Sleep(TOTAL_AMPLITUDE - busySpan[j]);
}
return 0;
}
显然,双核的情况下还是不尽人意的。
想到windows下API中有GetCurrentProcess和SetProcessAffinityMask,更改之:
#include "windows.h"
#include "stdio.h"
#include "math.h"
const int SAMPLING_COUNT = 200;
const double PI = 3.1415926535;
const int TOTAL_AMPLITUDE = 300;
int _tmain(int argc, _TCHAR* argv[])
{
SetProcessAffinityMask(
GetCurrentProcess(),
0x00000001
);
DWORD buySpan[SAMPLING_COUNT];
int amplintude = TOTAL_AMPLITUDE / 2;
double radian = 0.0;
double radianIncrement = 2.0 / (double)SAMPLING_COUNT;
for (int i = 0; i < SAMPLING_COUNT; ++i)
{
busySpan[i] = (DWORD)(amplitude + (sin(PI * radian) * amplitude));
radian += radianIncrement;
}
DWORD startTime = 0;
for (int j = 0;; j = (j + 1) % SAMPLING_COUNT)
{
startTime = GetTickCount();
while ((GetTickCount() - startTime) <= busySpan[j]);
Sleep(TOTAL_AMPLITUDE - busySpan[j]);
}
return 0;
}
暂时优快云不知道怎么上传不了图了...以后补上吧.....
大体是想就是控制一个周期内的CPU工作情况,而至于图像的生成,和win32课程上的生成方式类似的,算法设计的不多,主要是对API的一种了解,《编程之美》上说,如果你对上面的几个API了解并能应用了,你可以在简历上写“精通windows”了.....
PS中秋节快乐。