朱辉(茶水): 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 ...
随机推荐
- Mysql面试题及千万级数据查询优化
今天在说Mysql查询优化之前,我先说一个常见的面试题,并带着问题深入探讨研究.这样会让大家有更深入的理解. 一,Mysql数据库中一个表里有一千多万条数据,怎么快速的查出第900万条后的100条数据 ...
- Git & Github 使用教程【1】入门篇
Github教程 1-1 版本管理工具简介 主要作用:备份文件.记录历史.回到过去.多端共享.独挡一面.团队协作 2-1 版本管理工具发展历史 3-1 Git下载和安装[略] 3-2 linux下安装 ...
- Cassandra官方介绍及安装
Cassandra官方介绍及安装 这个数据库有很高的伸缩性和可用性,你完全不需要向性能妥协.在硬件或者云设施上做修改 官网:Cassandra官网 一.简介 cassandra这个数据库有很高的伸缩性 ...
- JavaScript 实用技巧
1数组中删除重复 let arr = [1,2,4,3,6,4] Array.from(new Set(arr)) // es6中 .from()[1,2,4,3,6] [...new Set(arr ...
- Log4j slf4j 配置简单介绍
Log4j slf4j 配置简单介绍 先借鉴一篇很好的文章 为什么要使用SLF4J而不是Log4J import org.slf4j.Logger; import org.slf4j.LoggerFa ...
- Java内存模型(JMM)详解
在Java JVM系列文章中有朋友问为什么要JVM,Java虚拟机不是已经帮我们处理好了么?同样,学习Java内存模型也有同样的问题,为什么要学习Java内存模型.它们的答案是一致的:能够让我们更好的 ...
- Jenkins 2.60.x 2种发送邮件方式
1.1 默认发邮件的配置方式 1.1.1 系统级别 邮件配置 1.1.2 项目级别 邮件配置 测试构建失败是否会发邮件: 控制台输出:提示已发送邮件给项目配置指定的两个邮箱地址. 1.1.2.1 查 ...
- MySQL查询-分组取组中某字段最大(小)值所有记录
最近做东西的时候,用到一个数据库的查询.将记录按某个字段分组,取每个分组中某个字段的最大值的所有记录.举栗子来说. 已知分数表“score”,包含字段“id", "name&quo ...
- Git学习笔记----基础运用
安装Git Windows: 进入官网下载或百度网盘下载 Git(V2.23_x64) 提取码:uf2x Ubuntu: sudo apt-get -install git 安装完成之后打开git命令 ...
- Scrapy爬虫day2——简单运行爬虫
设置setting.py 修改机器人协议 ROBOTSTXT_OBEY = False 设置User-Agent DEFAULT_REQUEST_HEADERS = { 'Accept': 'text ...