朱辉(茶水): Linux Kernel iowait 时间的代码原理
本文系转载,著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
作者: 朱辉(茶水)
来源: 微信公众号linux阅码场(id: linuxdev)

作者介绍
朱辉,个人主页 http://teawater.github.io/,微信公众号茶水侃山(cschatcs)。
做过几年模拟器,做过几年GDB,在小米电视做过几年Linux内核优化,主要围绕MM。
现在在HyperHQ当软件工程师。
更新记录
2017.12.15:
对扩展文章的问题描述进行了精确化。
2017.12.10:
根据张骁和宋宝华老师的建议,将结尾的错误进行了修正。
增加一篇扩展阅读。
增加了对CPU负载均衡问题的讲解。
之前在我热爱的公众号Linux阅码场看到The precise meaning of I/O wait time in Linux 这篇文章,感觉写的不错,就是没有落实到源码上感觉稍微有点晦涩,于是自己读了一下代码。
当task发生iowait的时候,内核对他们的处理方法是将task切换出去,让可运行的task先运行,而在切换出去前,会将其in_iowait设置为1,再次被唤醒的时候in_iowait被设置为原值。相关函数io_schedule,io_schedule_timeout,mutex_lock_io,mutex_lock_io_nested。
例如:

由此可见in_iowait表明了这个task是否在iowait。
另外要注意的是,这几个切换函数除了mutex_lock_io,mutex_lock_io_nested会设置task运行状态为TASK_UNINTERRUPTIBLE外,内核在调用io_schedule,io_schedule_timeout前都会设置task运行状态TASK_UNINTERRUPTIBLE。
在进程切换函数__schedule在切换task的时候,如果被切换出的task的in_iowait为真,则会对这个CPU的运行队列rq结构中的nr_iowait加1。
因为前面对task已经被设置为TASK_UNINTERRUPTIBLE,则task需要被唤醒,对nr_iowait的减少操作也是在task唤醒函数来做的。
由此可见nr_iowait可以表明某CPU上是否有task在iowait,以及数量。
因为处于iowait的task是TASK_UNINTERRUPTIBLE状态,其并不在就绪队列中,所以其也没有被CPU负载均衡到其他CPU的可能,所以nr_iowait也不需要处理负载均衡问题。
当累加系统idle时间的时候,如果CPU的nr_iowait为真,也就是当前这个cpu有task在等待iowait,则记录为iowait时间。
在打开NO_HZ的内核中,相关代码在update_ts_time_stats。

而没打开的则在 account_idle_time。

当相关/proc/stat接口被访问时,get_iowait_time就会访问这个时间并返回。
综上所述,iowait时间就是CPU idle时间,但是这时候CPU上不是完全没TASK需要运行,而是休眠的task中有一个或者若干个是iowait的task。
当然idle和iowait的时候CPU上还有idle task。
最后推荐一篇阿里内核组的文章作为扩展阅读Kernel Documents/new iowait calculation (http://link.zhihu.com/?target=http%3A//kernel.taobao.org/index.php%3Ftitle%3DKernel_Documents/new_iowait_calculation)
比较有意思是这里:
+ wait_event_interruptible_hrtimeout(ctx->wait,
+ aio_read_events(ctx, min_nr, nr, event, &ret), until);
无论超时值until是什么值,都会调用wait_event_interruptible_hrtimeout,虽然是hrtimer实时性已经很高,但是在用来实际处理wait的宏__wait_event_hrtimeout可以看到hrtimer初始化使用的是:
hrtimer_start_range_ns(&__t.timer, timeout,\
current->timer_slack_ns,\
HRTIMER_MODE_REL);\
其中第三个参数current->timer_slack_ns是传递给hrtimer的触发范围,因为hrtimer实时性高,但是频繁触发系统显然受不了,所以每次hrtimer触发都会将时间范围内的timer都处理掉(见__hrtimer_run_queues)。所以timeout+current->timer_slack_ns才是设置的hrtimer的最后触发时间,current->timer_slack_ns的默认值是50000,也就是代表50000纳秒。也就是这个时钟最久会在50000纳秒后触发,当然也可能被之前的hrtimer触发。
所以在wait_event_interruptible_hrtimeout中,一旦ctx->wait未能就绪,即使设置超时时间为0,也很可能要调用一次schedule,这导致iowait时间相差很大,也还很大幅度伤害了性能。
而这个问题也被5f785de588735306ec4d7c875caf9d28481c8b21进行了修复,这段代码改成了:
- wait_event_interruptible_hrtimeout(ctx->wait,
- aio_read_events(ctx, min_nr, nr, event, &ret), until);
+ if (until.tv64 == 0)
+ aio_read_events(ctx, min_nr, nr, event, &ret);
+ else
+ wait_event_interruptible_hrtimeout(ctx->wait,
+ aio_read_events(ctx, min_nr, nr, event, &ret),
+ until);
从而在until为0的时候,直接调用aio_read_events。应该就不会再有那么明显的iowait问题了,另外也因此这个修复让io_getevents的调用得到了超过百倍的性能提升。
当然这个iowait不够精确的原因还是存在,一旦因为需要发生task切换,还是会有不够精确的问题。
最后要吐槽一下aio的设计,都aio了还需要wait吗?
更多精彩更新中……欢迎关注微信公众号:linux阅码场(id: linuxdev)
朱辉(茶水): Linux Kernel iowait 时间的代码原理的更多相关文章
- Linux kernel Vhost-net 和 Virtio-net代码详解
场景 Host上运行qemu kvm虚拟机,其中虚拟机的网卡类型为virtio-net,而Host上virtio-net backend使用vhost-net 数据包进入虚拟机代码分析 首先看vhos ...
- linux kernel的cmdline参数解析原理分析【转】
转自:https://blog.csdn.net/skyflying2012/article/details/41142801 版权声明:本文为博主kerneler辛苦原创,未经允许不得转载. htt ...
- Linux Kernel系列 - 黄牛X内核代码凝视
Hanks.Wang - 专注于操作系统与移动安全研究.Linux-Kernel/SELinux/SEAndroid/TrustZone/Encription/MDM Mail - byhank ...
- Python classes to extract information from the Linux kernel /proc files.
python/python-linux-procfs/python-linux-procfs.git - Python classes to extract information from the ...
- karottc A Simple linux-virus Analysis、Linux Kernel <= 2.6.37 - Local Privilege Escalation、CVE-2010-4258、CVE-2010-3849、CVE-2010-3850
catalog . 程序功能概述 . 感染文件 . 前置知识 . 获取ROOT权限: Linux Kernel <= - Local Privilege Escalation 1. 程序功能概述 ...
- linux kernel 杂谈
首先介绍一下背景吧,工作三个星期了.复习了一波u-boot,跟了一下事件上报,搞了下平台设备,扣了一个内存检查代码. 想想生活是不是有点无聊.对啊,真的很无聊!!!! 无聊也没有办法啊,所以找点方法去 ...
- Intel 80x86 Linux Kernel Interrupt(中断)、Interrupt Priority、Interrupt nesting、Prohibit Things Whthin CPU In The Interrupt Off State
目录 . 引言 . Linux 中断的概念 . 中断处理流程 . Linux 中断相关的源代码分析 . Linux 硬件中断 . Linux 软中断 . 中断优先级 . CPU在关中断状态下编程要注意 ...
- CentOS7 + linux kernel 3.10.94 compile 简记
Linux kernel 一直以其开源著称,可以自己编译选择合适的模块,针对特定的系统可以有不同的编译选项 来源 此次编译的内核版本为3.10.94,从官网www.kernel.org下载而来,自己虚 ...
- Linux Kernel中断子系统来龙去脉浅析【转】
转自:http://blog.csdn.net/u011461299/article/details/9772215 版权声明:本文为博主原创文章,未经博主允许不得转载. 一般来说,在一个device ...
随机推荐
- Spring Boot 入门(七):集成 swagger2
本片文章是基于前一篇写的,<Spring Boot 入门(六):集成 treetable 和 zTree 实现树形图>,本篇主要介绍了spring boot集成swagger2.关于swa ...
- opencv实践::直线检测
问题描述 寻找英语试卷填空题的下划线,这个对后期的切图与自动 识别都比较重要. 解决思路 方法: 通过图像形态学操作来寻找直线,霍夫获取位置信息与显示. #include <opencv2/op ...
- 1.7.3.1版本ride乱码的解决方法
现象: 解决方式: 修改文件\Python36\Lib\site-packages\robotide\contrib\testrunner\testrunner.py 将latin1修改为mbcs 然 ...
- 【阿里云IoT+YF3300】7.物联网设备表达式运算
很多时候从设备采集的数据并不能直接使用,还需要进行处理一下.如果采用脚本处理,有点太复杂了,而采用表达式运算,则很方便地解决了此类问题. 一. 设备连接 运行环境搭建:Win7系统请下载相关的设备驱 ...
- 介绍Webflux
介绍Webflux 关于WebFlux 我们知道传统的Web框架,比如说:struts2,springmvc等都是基于Servlet API与Servlet容器基础之上运行的,在Servlet3.1之 ...
- Java11新特性 - Epsilon GC和ZGC
Java11中新增了两个GC,Epsilon GC和ZGC. Epsilon垃圾收集器 A NoOp Garbage Collector 没有操作的垃圾收集器 JDK上对这个特性的描述是:开发一个处理 ...
- Java基础(二十二)集合(4)Set集合
Set集合为集类型.集是最简单的一种集合,存放于集中的对象不按特定方式排序,只是简单地把对象加入集合中.对集中存放的对象的访问和操作时通过对象的引用进行的,所以,在集中不能存放重复对象. Set接口实 ...
- SpringBoot整合Swagger2(Demo示例)
写在前面 由于公司项目采用前后端分离,维护接口文档基本上是必不可少的工作.一个理想的状态是设计好后,接口文档发给前端和后端,大伙按照既定的规则各自开发,开发好了对接上了就可以上线了.当然这是一种非常理 ...
- ofd电子文档内容分析工具(分析文档、签章和证书)
前言 ofd是国家文档标准,其对标的文档格式是pdf.ofd文档是容器格式文件,ofd其实就是压缩包.将ofd文件后缀改为.zip,解压后可看到文件包含的内容. ofd文件分析工具下载:点我下载.获取 ...
- 第二十五章 system v消息队列(一)
IPC对象的持续性 随进程持续 :一直存在直到打开的最后一个进程结束.(如pipe和FIFO) 随内核持续 :一直存在直到内核自举(内核自举就是把主引导记录加载到内存,并跳转执行这段内存)或显示删除( ...