zoukankan      html  css  js  c++  java
  • CPU利用率问题:操作系统原理和API

    问题的提出:写一个程序,使得CPU的占用率可以听从用户的安排,第一种情况,CPU的占用率固定在50%,第二种情况,CPU的占用率为一条直线,具体占用率用参数表示;第三种情况,CPU的占用率状态是一条正弦曲线。

    分析:这个问题,不了解操作系统原理和内核代码的人看起来很玄乎。但此问题的本质是操作系统原理,即操作系统如何分配资源给用户程序。进而分析到应用程序级别可得,CPU忙的时间和CPU休眠的时间相等时,根据刷新出来的图像便保持在50%左右。写应用程序,会用到Windows的API。

    思路一:根据CPU的主频,计算每秒钟执行的指令条数,将循环用汇编代码表示,求得需要循环执行的次数。并且休眠同样的时间。

    核心的API:Sleep()  

    long GetCPUFreq()//获取CPU频率,单位: MHZ
    {
    	 int start1,start2;
    	 _asm rdtsc
    	 _asm mov start1,eax
    	  Sleep(50);
    	 _asm rdtsc
    	 _asm mov start2,eax
    	 return ((start2-start1)/50)/(1024);
    }
    
    
    //1-1
    void SimpleCpu()
    {
    	while(true)
    	{
    		//busy
    		for(int i=0;i<1181600000;i++)
    			;
    		//idle
    		Sleep(10);
    	}
    }//simplecpu
    

    思路二:使用GetTickCount()和Sleep()

    使用GetTickCount获得系统启动以来的时间,然后根据需要休眠的时间确定忙循环要做的时间。

    /GetTickCount和Sleep
    void GetSleepCpu()
    {
    	const DWORD busyTime=100;	//10毫秒
    	const DWORD idleTime=busyTime; //忙的时间和休眠的时间大致相当
    
    	INT64 startTime=0;
    	while(true)
    	{
    		DWORD startTime=GetTickCount();
    		//bust loop
    		while((GetTickCount()-startTime)<busyTime)
    			;
    		//idle loop
    		Sleep(idleTime);
    	}
    }//GetSleepCpu
    

    思路三:正弦曲线问题

    把2Pi等分,计算振幅,然后让CPU工作在相应的振幅处。

    void SineGraph()
    {
    	SetThreadAffinityMask(GetCurrentThread(), 1);   
    	//将0-2Pi之间等分成200份进行抽样,计算每个抽样点的振幅
    	//300ms是近似的值 6.28/200
    	const int SAMPLINE_COUNT=200;	//抽样点数量
    	const double PI=3.1415926535;	
    	const int TOTAL_AMPLITUDE=300;	//每个抽样点对应的时间片
    
    	DWORD busySpan[SAMPLINE_COUNT];	
    	int apmlitude=TOTAL_AMPLITUDE;	
    	double radian=0.0;
    	double radianIncrement=(2.0*PI)/(double)SAMPLINE_COUNT;	//增量
    
    	//计算每个抽样点的振幅
    	for(int i=0;i<SAMPLINE_COUNT;i++)
    	{
    		busySpan[i]=(DWORD)(apmlitude+(sin(PI*radian)*apmlitude));
    		radian+=radianIncrement;
    	}
    
    	DWORD startTime=0;
    	for(int j=0;;j=(j+1)%SAMPLINE_COUNT)
    	{
    		startTime=GetTickCount();
    		while((GetTickCount()-startTime)<=busySpan[j])
    			;
    		Sleep(TOTAL_AMPLITUDE-busySpan[j]);
    	}
    
    }//SineGraph
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int c;
    	cin>>c;
    	
    	switch(c)
    	{
    	case 1:
    		SimpleCpu();	//56%
    		break;
    	case 2:
    		GetSleepCpu();	//51% 52%
    		break;
    	case 3:
    		SineGraph();	//正弦曲线
    		break;
    	}
    	return 0;
    }
    

    多核CPU的情况下,程序是不一样的写法,此处不讨论。这道题主要考察对操作系统的理解。

  • 相关阅读:
    [rrdtool]监控和自己主动绘图,简单的监控.md
    64位Windows操作系统中的注冊表
    (转载)正向代理与反向代理的区别
    (转载)数据库表分割技术浅析(水平分割/垂直分割/库表散列)
    JavaWeb学习总结(四十九)——简单模拟Sping MVC
    JNDI学习总结(三)——Tomcat下使用Druid配置JNDI数据源
    JNDI学习总结(二)——Tomcat下使用C3P0配置JNDI数据源
    JNDI学习总结(一)——JNDI数据源的配置
    哈佛图书馆墙上的训言
    少走弯路的10条忠告
  • 原文地址:https://www.cnblogs.com/fistao/p/3169514.html
Copyright © 2011-2022 走看看