全球最实用的IT互联网信息网站!

AI人工智能P2P分享&下载搜索网页发布信息网站地图

当前位置:诺佳网 > 电子/半导体 > 嵌入式技术 >

看看Linux是怎么统计iowait比率的?

时间:2023-04-27 09:28

人气:

作者:admin

标签: CPU  LINUX内核  时钟中断 

导读:我们对系统性能进行优化时,一般会使用 top 命令来查看系统负载和系统中各个进程的运行情况,从而找出影响系统性能的因素。...

我们对系统性能进行优化时,一般会使用top命令来查看系统负载和系统中各个进程的运行情况,从而找出影响系统性能的因素。如下图所示:

f050fede-e47b-11ed-ab56-dac502259ad0.png

top

top命令会输出很多系统相关的信息,如:系统负载、系统中的进程数、CPU使用率和内存使用率等,这些信息对排查系统性能问题起着至关重要的作用。

本文主要介绍top命令中的iowait指标(如上图中红色方框所示)的含义和作用。

什么是iowait

什么是iowait?我们来看看 Linux 的解释:

Show the percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request.

中文翻译的意思就是:CPU 在等待磁盘 I/O 请求完成时,处于空闲状态的时间百分比(此时正在运行着idle进程)。

可以看出,如果系统处于iowait状态,那么必须满足以下两个条件:

系统中存在等待 I/O 请求完成的进程。

系统当前正处于空闲状态,也就是说没有可运行的进程。

iowait统计原理

既然我们知道了iowait的含义,那么接下来看看 Linux 是怎么统计iowait的比率的。

Linux 会把iowait占用的时间输出到/proc/stat文件中,我们可以通过一下命令来获取到iowait占用的时间:

cat/proc/stat

命令输出如下图所示:

f098ae5a-e47b-11ed-ab56-dac502259ad0.png

stat

红色方框中的数据就是iowait占用的时间。

我们可以每隔一段时间读取一次/proc/stat文件,然后把两次获取到的iowait时间进行相减,得到的结果是这段时间内,CPU处于iowait状态的时间。接着再将其除以总时间,得到iowait占用总时间的比率。

现在我们来看看/proc/stat文件是怎样获取iowait的时间的。

在内核中,每个 CPU 都有一个cpu_usage_stat结构,主要用于统计 CPU 一些信息,其定义如下:

structcpu_usage_stat{
cputime64_tuser;
cputime64_tnice;
cputime64_tsystem;
cputime64_tsoftirq;
cputime64_tirq;
cputime64_tidle;
cputime64_tiowait;
cputime64_tsteal;
cputime64_tguest;
cputime64_tguest_nice;
};

cpu_usage_stat结构的iowait字段记录了 CPU 处于iowait状态的时间。

所以要获取系统处于iowait状态的总时间,只需要将所有 CPU 的iowait时间相加即可,代码如下(位于源文件fs/proc/stat.c):

staticintshow_stat(structseq_file*p,void*v)
{
u64iowait;
...
//1.遍历系统中的所有CPU
for_each_possible_cpu(i){
...
//2.获取CPU对应的iowait时间,并相加
iowait=cputime64_add(iowait,kstat_cpu(i).cpustat.iowait);
...
}
...
return0;
}

show_stat()函数首先会遍历所有 CPU,然后读取其iowait时间,并且将它们相加。

增加iowait时间

从上面的分析可知,每个 CPU 都有一个用于统计iowait时间的计数器,那么什么时候会增加这个计数器呢?

答案是:系统时钟中断。

在系统时钟中断中,会调用account_process_tick()函数来更新 CPU 的时间,代码如下:

voidaccount_process_tick(structtask_struct*p,intuser_tick)
{
cputime_tone_jiffy_scaled=cputime_to_scaled(cputime_one_jiffy);
structrq*rq=this_rq();

//1.如果当前进程处于用户态,那么增加用户态的CPU时间
if(user_tick){
account_user_time(p,cputime_one_jiffy,one_jiffy_scaled);
}
//2.如果前进程处于内核态,并且不是idle进程,那么增加内核态CPU时间
elseif((p!=rq->idle)||(irq_count()!=HARDIRQ_OFFSET)){
account_system_time(p,HARDIRQ_OFFSET,cputime_one_jiffy,
one_jiffy_scaled);
}
//3.如果当前进程是idle进程,那么调用account_idle_time()函数进行处理
else{
account_idle_time(cputime_one_jiffy);
}
}

我们主要关注当前进程是idle进程的情况,这是内核会调用account_idle_time()函数进行处理,其代码如下:

voidaccount_idle_time(cputime_tcputime)
{
structcpu_usage_stat*cpustat=&kstat_this_cpu.cpustat;
cputime64_tcputime64=cputime_to_cputime64(cputime);
structrq*rq=this_rq();

//1.如果当前有进程在等待IO请求的话,那么增加iowait的时间
if(atomic_read(&rq->nr_iowait)>0){
cpustat->iowait=cputime64_add(cpustat->iowait,cputime64);
}
//2.否则增加idle的时间
else{
cpustat->idle=cputime64_add(cpustat->idle,cputime64);
}
}

account_idle_time()函数的逻辑比较简单,主要分以下两种情况进行处理:

如果当前有进程在等待 I/O 请求的话,那么增加iowait的时间。

如果当前没有进程在等待 I/O 请求的话,那么增加idle的时间。

所以,从上面的分析可知,要增加iowait的时间需要满足以下两个条件:

当前进程是idle进程,也就是说 CPU 处于空闲状态。

有进程在等待 I/O 请求完成。

进一步说,当 CPU 处于iowait状态时,说明 CPU 处于空闲状态,并且系统中有进程因为等待 I/O 请求而阻塞,也说明了 CPU 的利用率不够充分。

这时,我们可以使用异步 I/O(如iouring)来优化程序,使得进程不会被 I/O 请求阻塞。






审核编辑:刘清

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信