惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The GitHub Blog
The GitHub Blog
MyScale Blog
MyScale Blog
爱范儿
爱范儿
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
美团技术团队
Y
Y Combinator Blog
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
Martin Fowler
Martin Fowler
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
M
MIT News - Artificial intelligence
博客园 - Franky
V
Visual Studio Blog
I
InfoQ
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
博客园 - 司徒正美
L
LangChain Blog

博客园 - floodpeak

如何摆脱写文档时截屏的困扰 第六回:寻找交点,离胜利就剩一步 之 纽带 备忘录专题首页 转载系列首页 吐血三八二十四 澄清P问题、NP问题、NPC问题的概念 经典文章专题首页 第五回:设计数据结构,存好了数据好干活 上班途中如打仗 4月语言排行榜出炉,祝贺Visual Basic同比上升两名 第四回:掌握数学工具,没个好帮手怎么行 计算你的死亡时间 第三回:实现步骤显示,一步一步看得见 第二回:漫谈新思路,是我们自己干的时候了 第一回:回望经典,看看别人是怎么干的 参考文献的各种字母的含义 三角剖分专题首页 挑战系列首页 自制二进制时钟之三:跳动起来
CPU占用率算法
floodpeak · 2008-07-15 · via 博客园 - floodpeak


    windows2000任务管理器可以看到CPU的占用率。
    CPU是不能间断运行的,只要CPU上电就要运行指令,即使无事可做,也要执行NOP操作。所以windows的CPU占用率低并不是指CPU目前无事可做,而是指CPU可以从当前状态中腾出多少时间来做用户的事情。
    在多任务操作系统中的进程一般都实现了优先权算法,抢占式实时操作系统的高优先权进程能够立即抢占低优先权进程的CPU,而分时操作系统则一般等到当前进程的CPU时间片用完后再调度,但无论实时系统还是分时系统,高优先权进程在分配CPU时间上都比低优先权的进程占优势。
    可以定义PRIORITY_HIGHEST为操作系统定义的最高优先权,PRIORITY_LOWEST为操作系统定义的最低优先权,一般PRIORITY_HIGHEST的值就是0,PRIORITY_LOWEST是大于0的一个数,虽然这样会或多或少混淆HIGHEST和LOWEST的意思。在windows中PRIORITY_HIGHEST为0,是系统进程;PRIORITY_LOWEST不知道是多少,但一定是空闲进程,就是任务管理器中看到System Idle Process进程。在比PRIORITY_LOWEST低一级的(PRIORITY_LOWEST-1)有一个统计进程,姑且叫OSStat,就是用来统计CPU占用率的。
    在OS初始化时一定有一段时间是只有系统进程在运行的,因为初始化还没完成,没开始调度用户进程。这个时候OS可以对CPU进行计时,计算CPU一秒内可以执行多少次加法,比如可以写这样的代码

1 OSIdleCtr = 0L;         /* Clear idle counter   */
2 OSTimeDly(OS_TICKS_PER_SEC); /* Determine MAX. idle counter value for 1 second */
3 OSIdleCtrMax = OSIdleCtr;    /* Store maximum idle counter count in 1 second */
4 

    其中OSTimeDly是使系统所有进程(除Idle进程外)都挂起OS_TICKS_PER_SEC个时间片,而OS_TICKS_PER_SEC的值可以通过晶振的频率直接计算得到指令周期再由CPU划分,也可以通过CPU提供的指令得到指令周期再由CPU划分。
    在Idle进程中加入这样的代码

OSIdleCtr++;

    到这里OSTimeDly(OS_TICKS_PER_SEC)的意义就很明确了,由于挂起其他进程,这样系统中只有Idle在运行,Idle对OSIdleCtr累加就不会被其他更高优先级的进程中断而造成计算不准确。
    如此就得到了1秒中Idle进程可以执行的最大加法次数,为什么Idle进程对OSIdleCtr的累加就是CPU一秒内最大加法次数呢,因为其他进程都被挂起了1秒,在这1秒内CPU只执行Idle的代码嘛,所以Idle对OSIdleCtr的累加可以代表一个系统的最大执行能力,不可能有其他方式可以在1秒内使OSIdleCtr的值累加到超过这个值。
    另外Idle的其他代码不会影响OSIdleCtr的准确性,因为可以把定义‘系统执行加法的最大次数’改成‘系统执行Idle过程的最大次数’,意义是不变的,仍然代表了CPU的执行能力。
    事实上Idle也是一个进程,所以也参与进程的调度算法,既然已经在Idle中加入了OSIdleCtr累加的算法,那么系统只需要在每秒钟中断的时候将OSIdleCtr初始化为0,则在系统正常运行的时候(用户进程已经开始)1秒钟内Idle对OSIdleCtr的累加就可以看成在普通用户状态下的CPU在1秒内的处理能力,因为这个时候用户进程已经开始参与调度,而Idle进程是系统中最低优先级的进程,其只在无用户任务的情况下调入,只要用户有其他任务,Idle都会挂起来等待,所以这个时候Idle对OSIdleCtr的累加就代表了在当前任务压力下CPU的空闲程度。因为OSIdleCtr每秒钟被复0一次,所以CPU的占用率自然也可以写成
    CPUUsage%=100*(1-OSIdleCtr/OSIdleCtrMax)这条公式的计算写在OSStat里,就形成了windows的CPU占用率形式。
    事实上,上面讨论的算法是ucos2系统的CPU占用率算法,ucos2是一个开源实时操作系统,通常用在嵌入式CPU中。