0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

朱辉:Linux Kernel iowait 时间的代码原理以及内核拓展文章介绍

Linux阅码场 2018-01-05 10:09 次阅读

作者简介

朱辉,做过几年模拟器,做过几年GDB,在小米电视做过几年Linux内核优化,主要围绕MM。

现在在HyperHQ当软件工程师

之前在我热爱的公众号Linuxer看到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。

例如:

朱辉:Linux Kernel iowait 时间的代码原理以及内核拓展文章介绍

由此可见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。

朱辉:Linux Kernel iowait 时间的代码原理以及内核拓展文章介绍

而没打开的则在 account_idle_time。

朱辉:Linux Kernel iowait 时间的代码原理以及内核拓展文章介绍

当相关/proc/stat接口被访问时,get_iowait_time就会访问这个时间并返回。

综上所述,iowait时间就是CPU idle时间,但是这时候CPU上不是完全没TASK需要运行,而是休眠的task中有一个或者若干个是iowait的task。

当然idle和iowait的时候CPU上还有idle task。

最后推荐一篇阿里内核组的文章作为扩展阅读Kernel 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吗?

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    3

    文章

    1357

    浏览量

    40177
  • Linux
    +关注

    关注

    87

    文章

    11191

    浏览量

    208627
  • 代码
    +关注

    关注

    30

    文章

    4708

    浏览量

    68176

原文标题:朱辉(茶水): Linux Kernel iowait 时间的代码原理

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何编译Linux Kernel

    整个Linux内核编译的过程非常简单,但是内核编译需要花费很长的时间。因为Linux内核
    发表于 06-07 16:26 1.1w次阅读
    如何编译<b class='flag-5'>Linux</b> <b class='flag-5'>Kernel</b>

    [分享资料]Linux Kernel Development Third Edition (Linux内核设计与实现)

    、进程调度、时间管理和定时器、系统调用接口、内存寻址、内存管理和页缓存、VFS、内核同步以及调试技术等。同时《Linux内核设计与实现(原书
    发表于 09-12 00:17

    编译你自己的Linux内核Kernel

    摘要:你马上就会发现,你也可以获得(get),配置(configure),编译(compile)和安装(install)属于你自己的Linux内核Kernel)。目录:引言安装内核
    发表于 11-10 12:16

    介绍一下Linux内核编译和更新的操作流程

    rk3399-firefly-linux.img -j4命令开始编译内核。  内核编译时间视电脑配置而定,内核
    发表于 06-21 09:58

    Linux内核代码漫游

    Linux内核代码漫游 本章试图以顺序的方式来解释Linux代码,以帮助读者对源代码的体系
    发表于 02-09 15:27 26次下载

    linux内核kernel-api

    linux内核kernel-api,不知道从哪儿找的了,但是你如果想要做内核编程,这是一部api函数详尽的工具书!!!五星推荐
    发表于 10-30 17:16 19次下载

    怎样去读Linux内核代码

    怎样去读Linux内核代码
    发表于 10-25 10:15 13次下载
    怎样去读<b class='flag-5'>Linux</b><b class='flag-5'>内核</b>源<b class='flag-5'>代码</b>

    linux kernel工作队列及源码解析

    1. 前言 工作队列(workqueue)的Linux内核中的定义的用来处理不是很紧急事件的回调方式处理方法。 以下代码linux内核版本
    发表于 10-27 10:19 0次下载

    嵌入式未来还是Linux的天下,并通过内核学习来阐述kernel的机理

    Kernel入门,要选本好的入门书籍,我从网上download一本《Linux内核设计与实现》。这本书简单易读,有OS基础和Linux应用基础的人一读即懂,我现已阅过3章,感觉很不错,
    的头像 发表于 01-24 08:47 3711次阅读

    Linux Kernel 5.2.2震撼发布!

    在首个维护版本更新之后,在kernel.org官网上已经将Linux Kernel 5.2分支标记为“Stable”,意味着已经准备好大规模部署了,所有GNU/Linux发行版本都应该
    的头像 发表于 08-09 17:01 2843次阅读

    快速理解什么是Linux内核以及Linux内核的内容

    01 前言 本文主要讲解什么是Linux内核以及通过多张图片展示Linux内核的作用与功能,以便于读者能快速理解什么是
    的头像 发表于 10-21 12:02 4234次阅读
    快速理解什么是<b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>以及</b><b class='flag-5'>Linux</b><b class='flag-5'>内核</b>的内容

    自由软件媒体Linux Kernel 5.10华为代码贡献排名第一

     自由软件媒体 LWN.netLinux Kernel 5.10 代码贡献,华为排名第一 在 Linux Kernel 5.10(下文简称“5.10 版本”)版本中,华为提交的补丁数量
    的头像 发表于 01-15 14:05 2643次阅读
    自由软件媒体<b class='flag-5'>Linux</b> <b class='flag-5'>Kernel</b> 5.10华为<b class='flag-5'>代码</b>贡献排名第一

    Linux_Kernel_Developments内核开发

    Linux_Kernel_Developments内核开发详细说明。
    发表于 04-07 14:27 37次下载
    <b class='flag-5'>Linux_Kernel</b>_Developments<b class='flag-5'>内核</b>开发

    Linux 6.1发布,微软贡献Linux内核代码

    此外,公告中并没有提及 Linux 6.1 是否是 LTS 版本。按照 Linux 内核维护者 Greg Kroah-Hartman 的说法,Linux
    的头像 发表于 12-14 09:54 1154次阅读

    Linux内核代码的静态检查

    Linus在2004年开发了kernel代码静态检查工具,可以检查出kernel中潜在的风险代码
    的头像 发表于 06-05 14:50 947次阅读