• 我的订阅
  • 科技

linux中cpu利用率是如何算出来的?

类别:科技 发布时间:2023-02-22 19:21:00 来源:浅语科技

在线上服务器观察线上服务运行状态的时候,绝大多数人都是喜欢先用top命令看看当前系统的整体cpu利用率。例如,随手拿来的一台机器,top命令显示的利用率信息如下

linux中cpu利用率是如何算出来的?

这个输出结果说简单也简单,说复杂也不是那么容易就能全部搞明白的。例如:

问题1:top输出的利用率信息是如何计算出来的,它精确吗?

问题2:ni这一列是nice,它输出的是cpu在处理啥时的开销?

问题3:wa代表的是iowait,那么这段时间中cpu到底是忙碌还是空闲?

今天我们对cpu利用率统计进行深入的学习。通过今天的学习,你不但能了解cpu利用率统计实现细节,还能nice、iowait等指标有更深入的理解。

区别于以往的文章,今天我们不直接进入Linux实现,而是先从自己的思考开始!一、先思考一下

抛开Linux的实现先不谈,如果有如下需求,有一个四核服务器,上面跑了四个进程。

linux中cpu利用率是如何算出来的?

让你来设计计算整个系统cpu利用率的这个需求,支持像top命令这样的输出,满足以下要求:

cpu使用率要尽可能地准确

要能地体现秒级瞬时cpu状态

可以先停下来阅读思考几分钟。

linux中cpu利用率是如何算出来的?

好,思考结束。经过思考你会发现,这个看起来很简单的需求,实际还是有点小复杂的。

其中一个思路是把所有进程的执行时间都加起来,然后再除以系统执行总时间*4。

linux中cpu利用率是如何算出来的?

这个思路是没问题的,用这种方法统计很长一段时间内的cpu利用率是可以的,统计也足够的准确。

但只要用过top你就知道top输出的cpu利用率并不是长时间不变的,而是默认3秒为单位会动态更新一下(这个时间间隔可以使用-d设置)。我们的这个方案体现总利用率可以,体现这种瞬时的状态就难办了。你可能会想到那我也3秒算一次不就行了?但这个3秒的时间从哪个点开始呢。粒度很不好控制。

上一个思路问题核心就是如何解决瞬时问题。提到瞬时状态,你可能就又来思路了。那我就用瞬时采样去看,看看当前有几个核在忙。四个核中如果有两个核在忙,那利用率就是50%。

这个思路思考的方向也是正确的,但是问题有两个:

你算出的数字都是25%的整数倍

这个瞬时值会导致cpu使用率显示的剧烈震荡。

比如下图:

linux中cpu利用率是如何算出来的?

在t1的瞬时状态看来,系统的cpu利用率毫无疑问就是100%,但在t2时间看来,使用率又变成0%了。思路方向是对的,但显然这种粗暴的计算无法像top命令一样优雅地工作。

我们再改进一下它,把上面两个思路结合起来,可能就能解决我们的问题了。在采样上,我们把周期定的细一些,但在计算上我们把周期定的粗一些。

我们引入采用周期的概念,定时比如每1毫秒采样一次。如果采样的瞬时,cpu在运行,就将这1ms记录为使用。这时会得出一个瞬时的cpu使用率,把它都存起来。

linux中cpu利用率是如何算出来的?

在统计3秒内的cpu使用率的时候,比如上图中的t1和t2这段时间范围。那就把这段时间内的所有瞬时值全加一下,取个平均值。这样就能解决上面的问题了,统计相对准确,避免了瞬时值剧烈震荡且粒度过粗(只能以25%为单位变化)的问题了。

可能有同学会问了,假如cpu在两次采样中间发生变化了呢,如下图这种情况。

linux中cpu利用率是如何算出来的?

在当前采样点到来的时候,进程A其实刚执行完,有一点点时间没有既没被上一个采样点统计到,本次也统计不到。对于进程B,其实只开始了一小段时间,把1ms全记上似乎有点多记了。

确实会存在这个问题,但因为我们的采样是1ms一次,而我们实际查看使用的时候最少也有是秒级别地用,会包括有成千上万个采样点的信息,所以这种误差并不会影响我们对全局的把握。

事实上,Linux也就是这样来统计系统cpu利用率的。虽然可能会有误差,但作为一项统计数据使用已经是足够了的。在实现上,Linux是将所有的瞬时值都累加到某一个数据上的,而不是真的存了很多份的瞬时数据。

接下来就让我们进入Linux来查看它对系统cpu利用率统计的具体实现。二、top命令使用数据在哪儿

上一节我们说的Linux在实现上是将瞬时值都累加到某一个数据上的,这个值是内核通过/proc/stat伪文件来对用户态暴露。Linux在计算系统cpu利用率的时候用的就是它。

整体上看,top命令工作的内部细节如下图所示。

linux中cpu利用率是如何算出来的?

top命令访问/proc/stat获取各项cpu利用率使用值

内核调用stat_open函数来处理对/proc/stat的访问

内核访问的数据来源于kernel_cpustat数组,并汇总

打印输出给用户态

接下来我们把每一步都展开来详细看看。

通过使用strace跟踪top命令的各种系统调用,可以看的到它对该文件的调用。# strace topopenat(AT_FDCWD, "/proc/stat", O_RDONLY) = 4openat(AT_FDCWD, "/proc/2351514/stat", O_RDONLY) = 8openat(AT_FDCWD, "/proc/2393539/stat", O_RDONLY) = 8

除了/proc/stat外,还有各个进程细分的/proc/{pid}/stat,是用来计算各个进程的cpu利用率时使用的。

内核为各个伪文件都定义了处理函数,/proc/stat文件的处理方法是proc_stat_operations。//file:fs/proc/stat.cstatic int __init proc_stat_init(void){ proc_create("stat", 0, NULL, &proc_stat_operations); return 0;}static const struct file_operations proc_stat_operations = { .open = stat_open, };

proc_stat_operations中包含了该文件时对应的操作方法。当打开/proc/stat文件的时候,stat_open就会被调用到。stat_open依次调用single_open_size,show_stat来输出数据内容。我们来看看它的代码://file:fs/proc/stat.cstatic int show_stat(struct seq_file *p, void *v){ u64 user, nice, system, idle, iowait, irq, softirq, steal; for_each_possible_cpu(i) { struct kernel_cpustat *kcs = &kcpustat_cpu(i); user += kcs->cpustat[CPUTIME_USER]; nice += kcs->cpustat[CPUTIME_NICE]; system += kcs->cpustat[CPUTIME_SYSTEM]; idle += get_idle_time(kcs, i); iowait += get_iowait_time(kcs, i); irq += kcs->cpustat[CPUTIME_IRQ]; softirq += kcs->cpustat[CPUTIME_SOFTIRQ]; ... } //转换成节拍数并打印出来 seq_put_decimal_ull(p, "cpu ", nsec_to_clock_t(user)); seq_put_decimal_ull(p, " ", nsec_to_clock_t(nice)); seq_put_decimal_ull(p, " ", nsec_to_clock_t(system)); seq_put_decimal_ull(p, " ", nsec_to_clock_t(idle)); seq_put_decimal_ull(p, " ", nsec_to_clock_t(iowait)); seq_put_decimal_ull(p, " ", nsec_to_clock_t(irq)); seq_put_decimal_ull(p, " ", nsec_to_clock_t(softirq)); ...}

在上面的代码中,for_each_possible_cpu是在遍历存储着cpu使用率数据的kcpustat_cpu变量。该变量是一个percpu变量,它为每一个逻辑核都准备了一个数组元素。里面存储着当前核所对应各种事件,包括user、nice、system、idel、iowait、irq、softirq等。

在这个循环中,将每一个核的每种使用率都加起来。最后通过seq_put_decimal_ull将这些数据输出出来。

linux中cpu利用率是如何算出来的?

注意,在内核中实际每个时间记录的是纳秒数,但是在输出的时候统一都转化成了节拍单位。至于节拍单位多长,下一节我们介绍。总之,/proc/stat的输出是从kernel_cpustat这个percpu变量中读取出来的。

我们接着再看看这个变量中的数据是何时加进来的。三、统计数据怎么来的

前面我们提到内核是以采样的方式来统计cpu使用率的。这个采样周期依赖的是Linux时间子系统中的定时器。

Linux内核每隔固定周期会发出timerinterrupt(IRQ0),这有点像乐谱中的节拍的概念。每隔一段时间,就打出一个拍子,Linux就响应之并处理一些事情。

linux中cpu利用率是如何算出来的?

一个节拍的长度是多长时间,是通过CONFIG_HZ来定义的。它定义的方式是每一秒有几次timerinterrupts。不同的系统中这个节拍的大小可能不同,通常在1ms到10ms之间。可以在自己的Linuxconfig文件中找到它的配置。# grep ^CONFIG_HZ /boot/config-5.4.56.bsk.10-64CONFIG_HZ=1000

从上述结果中可以看出,我的机器的每秒要打出1000次节拍。也就是每1ms一次。

每次当时间中断到来的时候,都会调用update_process_times来更新系统时间。更新后的时间都存储在我们前面提到的percpu变量kcpustat_cpu中。

linux中cpu利用率是如何算出来的?

我们来详细看下汇总过程update_process_times的源码,它位于kernel/time/timer.c文件中。//file:kernel/time/timer.cvoid update_process_times(int user_tick){ struct task_struct *p = current; //进行时间累积处理 account_process_tick(p, user_tick); }

这个函数的参数user_tick值得是采样的瞬间是处于内核态还是用户态。接下来调用account_process_tick。//file:kernel/sched/cputime.cvoid account_process_tick(struct task_struct *p, int user_tick){ cputime = TICK_NSEC; ... if (user_tick) //3.1 统计用户态时间 account_user_time(p, cputime); else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET)) //3.2 统计内核态时间 account_system_time(p, HARDIRQ_OFFSET, cputime); else //3.3 统计空闲时间 account_idle_time(cputime);}

在这个函数中,首先设置cputime=TICK_NSEC,一个TICK_NSEC的定义是一个节拍所占的纳秒数。接下来根据判断结果分别执行account_user_time、account_system_time和account_idle_time来统计用户态、内核态和空闲时间。3.1用户态时间统计//file:kernel/sched/cputime.cvoid account_user_time(struct task_struct *p, u64 cputime){ //分两种情况统计用户 CPU 的使用情况 int index; index = (task_nice(p) 0) ? CPUTIME_NICE : CPUTIME_USER; //将时间累积到 /proc/stat 中 task_group_account_field(p, index, cputime); }

account_user_time函数主要分两种情况统计:

如果进程的nice值大于0,那么将会增加到CPU统计结构的nice字段中。

如果进程的nice值小于等于0,那么增加到CPU统计结构的user字段中。

看到这里,开篇的问题2就有答案了,其实用户态的时间不只是user字段,nice也是。之所以要把nice分出来,是为了让Linux用户更一目了然地看到调过nice的进程所占的cpu周期有多少。

我们平时如果想要观察系统的用户态消耗的时间的话,应该是将top中输出的user和nice加起来一并考虑,而不是只看user!

接着调用task_group_account_field来把时间加到前面我们用到的kernel_cpustat内核变量中。//file:kernel/sched/cputime.cstatic inline void task_group_account_field(struct task_struct *p, int index, u64 tmp){ __this_cpu_add(kernel_cpustat.cpustat[index], tmp); ...}3.2内核态时间统计

我们再来看内核态时间是如何统计的,找到account_system_time的代码。//file:kernel/sched/cputime.cvoid account_system_time(struct task_struct *p, int hardirq_offset, u64 cputime){ if (hardirq_count() - hardirq_offset) index = CPUTIME_IRQ; else if (in_serving_softirq()) index = CPUTIME_SOFTIRQ; else index = CPUTIME_SYSTEM; account_system_index_time(p, cputime, index);}

内核态的时间主要分3种情况进行统计。

如果当前处于硬中断执行上下文,那么统计到irq字段中

如果当前处于软中断执行上下文,那么统计到softirq字段中

否则统计到system字段中

判断好要加到哪个统计项中后,依次调用account_system_index_time、task_group_account_field来将这段时间加到内核变量kernel_cpustat中//file:kernel/sched/cputime.cstatic inline void task_group_account_field(struct task_struct *p, int index, u64 tmp){ __this_cpu_add(kernel_cpustat.cpustat[index], tmp);}3.3空闲时间的累积

没错,在内核变量kernel_cpustat中不仅仅是统计了各种用户态、内核态的使用统计,空闲也一并统计起来了。

如果在采样的瞬间,cpu既不在内核态也不在用户态的话,就将当前节拍的时间都累加到idle中。//file:kernel/sched/cputime.cvoid account_idle_time(u64 cputime){ u64 *cpustat = kcpustat_this_cpu-cpustat; struct rq *rq = this_rq(); if (atomic_read(&rq-nr_iowait) 0) cpustat[CPUTIME_IOWAIT] += cputime; else cpustat[CPUTIME_IDLE] += cputime;}

在cpu空闲的情况下,进一步判断当前是不是在等待IO(例如磁盘IO),如果是的话这段空闲时间会加到iowait中,否则就加到idle中。从这里,我们可以看到iowait其实是cpu的空闲时间,只不过是在等待IO完成而已。

看到这里,开篇问题3也有非常明确的答案了,iowait其实是cpu在空闲状态的一项统计,只不过这种状态和idle的区别是cpu是因为等待io而空闲。四、总结

本文深入分析了Linux统计系统CPU利用率的内部原理。全文的内容可以用如下一张图来汇总:

linux中cpu利用率是如何算出来的?

Linux中的定时器会以某个固定节拍,比如1ms一次采样各个cpu核的使用情况,然后将当前节拍的所有时间都累加到user/nice/system/irq/softirq/io_wait/idle中的某一项上。

top命令是读取的/proc/stat中输出的cpu各项利用率数据,而这个数据在内核中的是根据kernel_cpustat来汇总并输出的。

回到开篇问题1,top输出的利用率信息是如何计算出来的,它精确吗?

/proc/stat文件输出的是某个时间点的各个指标所占用的节拍数。如果想像top那样输出一个百分比,计算过程是分两个时间点t1,t2分别获取一下stat文件中的相关输出,然后经过个简单的算术运算便可以算出当前的cpu利用率。

我也提供了一个简单的shell代码,你可以把它下载下来,用它来实际查看一下你服务器的cpu利用率,我放到我的github上了。

Github地址:https://github.com/ yanfeizhang/coder-kung-fu/blob/main/tests/cpu/test06/cpu_stat.sh

再说是否精确。这个统计方法是采样的,只要是采样,肯定就不是百分之百精确。但由于我们查看cpu使用率的时候往往都是计算1秒甚至更长一段时间的使用情况,这其中会包含很多采样点,所以查看整体情况是问题不大的。

另外从本文,我们也学到了top中输出的cpu时间项目其实大致可以分为三类:

第一类:用户态消耗时间,包括user和nice。如果想看用户态的消耗,要将user和nice加起来看才对。

第二类:内核态消耗时间,包括irq、softirq和system。

第三类:空闲时间,包括io_wait和idle。其中io_wait也是cpu的空闲状态,只不过是在等io完成而已。如果只是想看cpu到底有多闲,应该把io_wait和idle加起来才对。

以上内容为资讯信息快照,由td.fyun.cc爬虫进行采集并收录,本站未对信息做任何修改,信息内容不代表本站立场。

快照生成时间:2023-02-22 21:45:13

本站信息快照查询为非营利公共服务,如有侵权请联系我们进行删除。

信息原文地址:

史上最快AI芯片「Sohu」,速度10倍于B200,哈佛辍学生打造
...改进就能撬动硬件架构的更新。 速度超 H100 20 倍,FLOPS 利用率超 90%作为世界上首款 transformer ASIC(应用型专用集成电路)芯片
2024-06-27 09:24:00
一点不弱于windows!统信uos新版超级好用
...升超过900%,在开/关机、启动器启动、默认新安装系统CPU利用率、应用商店界面加载、多文件搜索、多文件解锁、QQ(linux)启动
2023-07-20 22:31:00
00后华裔小哥哈佛辍学组团挑战英伟达,史上最快AI芯片Sohu推理性能超H100二十倍!
...,从而允许其拥有更多的数学模块。结果就是,Sohu的FLOPS利用率高达90%以上;相比之下,使用TRT-LLM的GPU仅为为30%左右
2024-06-27 09:25:00
Sigmoid注意力一样强,苹果开始重新审视注意力机制
...。FLASHATTENTION 和 FLASHATTENTION2 通过优化 GPU 内存层次结构利用率来加速注意力计算
2024-09-19 12:02:00
地球石油消耗巨大,每日消耗堪抵一条河流,为何地球没有变轻呢?
...中,人们也可通过研发以及应用新的技术,从而使石油的利用率不断提高。这样也可减少对地球的消耗。与此同时,随着科技不断发展,人们也在积极开发利用一些可替代能源,如风能、太阳能以及
2023-12-27 10:23:00
字节跳动用ai优化linux内核:可“解放人类工程师”
...机器学习和AI还并没有达到万能的地步,预计还需要一段时间“才能取代Linux内核工程师”。
2023-11-24 02:01:00
一加Ace 5系列下周登场:全球首发风驰游戏内核:性能开挂
...拥有行业前所未见的超帧超画体验,GPU能力释放更充分,利用率更高,并且一加带来行业首个原生级120帧满帧持久流畅游戏体验,首次实现行业重载游戏原生级超帧+超画满血同开,功耗更
2024-12-12 16:45:00
技术规模化、复杂化?看作业帮如何利用OpenCloudOS解决技术难题!
...用对比在线服务的服务时延敏感,对服务 SLA 要求极高,利用率约 20%;而离线作业的服务时延不敏感,容错率高,利用率高达 60%
2023-06-30 11:01:00
Windows 11 初尝 Rust,36000 行内核代码已重写!
...布采取 Rust 重写之际,Mark Russinovich 便迫不及待地在第一时间与外界分享最新进度,难掩其对 Rust 语言的支持以及对 C/C++ 的嫌弃之情
2023-05-16 20:00:00
更多关于科技的资讯:
济宁能源融汇数易:为客户提供一站式数字服务
鲁网12月22日讯(记者 徐景春 周正杰)近日,记者来到济宁能源融汇数易采访,在融汇数易供应链综合服务平台监控中心,大屏幕上实时跳动着物流订单
2025-12-22 11:45:00
章剑华散文集《人生简史》新书出版分享会在南京召开
近日,由江苏散文学会主办的章剑华散文集《人生简史》新书出版分享会在南京召开,作家出版社有限公司董事长、社长鲍坚,江苏省作家协会原一级巡视员
2025-12-22 11:59:00
让AI有“情商” 具身情感智能平台在合肥发布
大皖新闻讯 随着人工智能技术的发展,“人机共生”已成必然。但是,当前绝大多数AI都严重缺乏“情商”,成为“人机共生”核心瓶颈之一
2025-12-22 12:04:00
从南京先锋书店的牛皮纸袋,到直播间里一句“想要治愈系书单”的即时回应,再到书店老板用盲盒一夜清空库存——图书盲盒作为将“纸质书”与“盲盒经济”糅合的产物
2025-12-22 12:14:00
友成基金会“香橙妈妈守艺计划”非遗创变营圆满落幕
2025年12月10日,友成基金会“香橙妈妈守艺计划”非遗焕新创变营在成都红仓·萌想星球107文创产业园开营。来自全国12个省市18区县的18位非遗受益人齐聚
2025-12-22 12:20:00
密切警企协作,米连科技以技术风控守护用户安全
在网络诈骗手段花样翻新、线上安全成为社会普遍关切的当下,营造清朗的网络空间需要社会各方的协同努力。作为在线情感社交领域的参与者
2025-12-22 13:20:00
景秀游戏《偃武》联动昆明市博物馆 让古滇文明触手可及
近日,景秀游戏旗下三国题材策略游戏《偃武》与昆明市博物馆正式启动“古滇文明数字复兴”计划,作为深耕数字娱乐领域的企业,景秀游戏始终希望以游戏为载体
2025-12-22 13:20:00
[摘要]随着人工智能技术的迅猛发展,高等教育正在经历深刻变革。这就要求高校在研究生培养模式上深化改革,大胆创新,积极推动人工智能(AI)技术在研究生培养中的融合路径与实践
2025-12-22 11:10:00
据媒体报道,今年以来,杭州知名“网红大楼”丽晶国际大厦——这座巅峰时期汇聚了近两万名主播与从业者、“一栋楼的GDP堪比一个县”的楼宇
2025-12-22 08:18:00
味蕾实验TASTELAB首次亮相引领零食行业科学化升级新征程
2025年12月20日,全新零食品牌味蕾实验TASTELAB在上海正式举办品牌发布会。本次活动以“让味觉被看见”为核心主题
2025-12-22 08:49:00
乌江榨菜全民创意共创:深度对话Z世代的品牌焕新
当传统品牌纷纷叩响年轻化的大门,仅靠历史底蕴已不足以触动Z世代的心。作为榨菜行业的领军者,乌江榨菜早已展开前瞻布局:从早年携手B站打破次元壁
2025-12-22 08:49:00
在保险行业向专业化、精细化、集约化发展的背景下,富德生命人寿以科技引领创新,积极布局集约化运营模式,构建起以总部为核心的全国理赔集中运营格局
2025-12-22 10:32:00
彰显实力!大咖素质训练营荣获“2025年度影响力教育品牌”奖项
近日,由新浪教育与微博教育联合主办的“新浪&微博 2025 教育盛典”于北京圆满落幕。大咖素质训练营凭借在素质教育领域的深耕积淀
2025-12-22 10:49:00
不用提前抢,西湖消费券带火实体商户:3天,星巴克黄龙广场店增收50%
作为促消费的首创实践,杭州西湖区“疯狂碰友日・西湖首发季”交出亮眼成绩单:首期三天,21 万市民参与“即碰即用”消费券活动
2025-12-22 10:49:00
近日,深耕青少年语言教育领域近十年的创业者徐萌,凭借其专业的课程体系与显著的教学成效,受到教育界广泛关注。徐萌毕业于中国传媒大学播音与主持专业
2025-12-22 08:49:00