北理工操作系统一CPU占用率控制实验报告Word格式.docx
《北理工操作系统一CPU占用率控制实验报告Word格式.docx》由会员分享,可在线阅读,更多相关《北理工操作系统一CPU占用率控制实验报告Word格式.docx(11页珍藏版)》请在冰点文库上搜索。
2.单核环境下,空死循环会导致100%的CPU占有率。
三、实验环境
硬件设备:
个人计算机。
系统软件:
windows操作系统,VisualC++6.0编译环境。
四、实验原理
通过观察任务管理器,它大约1s更新一次。
当CPU使用率为0时,SystemIdleProcess占用了CPU的空闲时间。
SystemIdleProcess在CPU空闲的的时候,发出一个IDLE命令,使CPU挂起(暂时停止工作),可有效的降低CPU内核的温度,无法终止。
在这个进程里出现的CPU占用数值并不是真正的占用而是体现的CPU的空闲率,也就说这个数值越大CPU的空闲率就越高,反之就是CPU的占用率越高。
当系统中的进程或者在等待用户输入,或者在等待某些事件的发生(发出I/O请求等待I/O响应),或者主动进入休眠状态(比如Sleep())。
在任务管理器的一个刷新周期内,CPU忙(执行应用程序)的时间和刷新周期总时间的比率,就是CPU的占用率,也就是说,任务管理器中显示的是每个刷新周期内CPU占用率的统计平均值。
单核环境下,空死循环会导致100%的CPU占有率。
对于多核CPU来说,同一个进程可能被CPU的任务分配器分配到不同的核心上执行,所以造成无法让任务管理器达到预想的效果。
其实打开任务管理器,可以看到多个CPU使用记录。
1、实现CPU占用率为一条直线,固定在50%。
GetTickCount()可以得到系统从启动到运行到现在所经历时间的毫秒值。
最多能统计到49.7天。
另外,利用Sleep()函数,最多也只能精确到1毫秒。
因此,可以在“毫秒”这个量级做操作和比较。
要操纵CPU的usage曲线,就需要使CPU在一段时间内跑busy和idle两个不同的循环,从而通过不同的时间比例来获得调节CPU占用率的控制。
利用GetTickCount()来实现busyloop的循环,用Sleep()实现idleloop。
#include<
cmath>
windows.h>
staticintPERIOD=60*1000;
//周期ms
constintCOUNT=300;
//一个周期计算次数
constdoubleGAP_LINEAR=100;
//线性函数时间间隔100ms
constdoublePI=3.1415926535898;
//PI
constdoubleGAP=(double)PERIOD/COUNT;
//周期函数时间间隔
constdoubleFACTOR=2*PI/PERIOD;
//周期函数的系数
staticdoubleRatio=0.5;
//线性函数的值0.5即50%
staticdoubleMax=0.9;
//方波函数的最大值
staticdoubleMin=0.1;
//方波函数的最小值
typedefdoubleFunc(double);
//定义一个函数类型Func*为函数指针
typedefvoidSolve(Func*calc);
//定义函数类型,参数为函数指针Func*
inlineDWORDget_time()
{
returnGetTickCount();
//操作系统启动到现在所经过的时间ms
}
doublecalc_sin(doublex)//调用周期函数solve_period的参数
return(1+sin(FACTOR*x))/2;
//y=1/2(1+sin(a*x))
doublecalc_fangbo(doublex)//调用周期函数solve_period的参数
//方波函数
if(x<
=PERIOD/2)returnMax;
elsereturnMin;
voidsolve_period(Func*calc)//线程函数为周期函数
doublex=0.0;
doublecache[COUNT];
for(inti=0;
i<
COUNT;
++i,x+=GAP)
cache[i]=calc(x);
intcount=0;
while
(1)
{
unsignedta=get_time();
if(count>
=COUNT)count=0;
doubler=cache[count++];
DWORDbusy=r*GAP;
while(get_time()-ta<
busy){}
Sleep(GAP-busy);
}
voidsolve_linear(Func*)//线程函数为线性函数,参数为空NULL
constunsignedBUSY=Ratio*GAP_LINEAR;
constunsignedIDLE=(1-Ratio)*GAP_LINEAR;
BUSY){}
Sleep(IDLE);
//voidsolve_nonperiod(Func*calc)//非周期函数的处理,暂没实验
//{
//doubletb=0;
//while
(1)
//{
//unsignedta=get_time();
//doubler=calc(tb);
//if(r<
0||r>
1)r=1;
//DWORDbusy=r*GAP;
//while(get_time()-ta<
//Sleep(GAP-busy);
////tb+=GAP;
//tb+=get_time()-ta;
//}
//}
voidrun(inti=1,doubleR=0.5,doubleT=60000,doublemax=0.9,doublemin=0.1)
//i为输出状态,R为直线函数的值,T为周期函数的周期,max方波最大值,min方波最小值
Ratio=R;
PERIOD=T;
Max=max;
Min=min;
Func*func[]={NULL,calc_sin,calc_fangbo};
//传给Solve的参数,函数指针数组
Solve*solve_func[]={solve_linear,solve_period};
//Solve函数指针数组
constintNUM_CPUS=2;
//双核,通用的可以用下面GetSystemInfo得到cpu数目
HANDLEhandle[NUM_CPUS];
DWORDthread_id[NUM_CPUS];
//线程id
//SYSTEM_INFOinfo;
//GetSystemInfo(&
info);
//得到cpu数目
//constintnum=info.dwNumberOfProcessors;
switch(i)
case1:
//cpu1,cpu2都输出直线
NUM_CPUS;
++i)
Func*calc=func[0];
Solve*solve=solve_func[0];
if((handle[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)solve,
(VOID*)calc,0,&
thread_id[i]))!
=NULL)//创建新线程
SetThreadAffinityMask(handle[i],i+1);
//限定线程运行在哪个cpu上
WaitForSingleObject(handle[0],INFINITE);
//等待线程结束
break;
case2:
//cpu1直线,cpu2正弦
Func*calc=func[i];
Solve*solve=solve_func[i];
case3:
//cpu1直线,cpu2方波
/*Func*calc=func[0];
*/
if((handle[0]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)solve_func[0],
(VOID*)func[0],0,&
thread_id[0]))!
SetThreadAffinityMask(handle[0],1);
Func*calc=func[2];
Solve*solve=solve_func[1];
if((handle[1]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)solve,
thread_id[1]))!
SetThreadAffinityMask(handle[1],2);
case4:
//cpu1正弦,cpu2方波
if((handle[0]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)solve_func[1],
(VOID*)func[1],0,&
default:
voidmain()
run(1,0.5);
//cpu1,cpu2都输出50%的直线
//run(2,0.5,30000);
//cpu10.5直线,cpu2正弦周期30000
//run(3);
//run(4,0.8,30000,0.95,0.5);
//cpu1正弦,cpu20.95-0.5的方波