第三章write()中已经提到要写的page加到了writeback queue后将有writeback thread将其真正写到block device上,而不是每一次写都直接写到media上。如果要绕过writeback机制直接写到media上,在open()的时候指定O_DIRECT即可。Writeback机制的好处总结起来主要是两点:

  • 加快write()的响应速度。因为media的读写相对于内存访问是较慢的。如果每个write()都访问media,势必很慢。将较慢的media访问交给writeback thread,而write()本身的thread里只在内存里操作数据,将数据交到writeback queue即返回。
  • 便于合并和排序 (merge and sort) 多个write,merge是将多个少量数据的write合并成几个大量数据的write,减少访问media的次数;sort是将无序的write按照其访问media上的block的顺序排序,减少磁头在media上的移动距离。

下面将说明writeback的活动机制。

  • 概念:writeback和bdi

从上面的阐述writeback的概念里可以看 出,writeback是文件系统的概念,writeback是指文件 (即inode)的部分数据由writeback thread写入medi a。这里就产生一个问题,一个media上可能有多个文件系统,如sda1上是ext4, sda2上是fat,但其实是在一个硬盘sda上,如果分别由不同的thread对sda1,sda2进行writeback的话,上面所说的排序(sort)功能将没有意义,因为可能thread1写了一会儿sda1,thread2又要把磁头移到别的地方去写sda2了。鉴于此,设计writeback机制时,writeback的主体应该是sda,而不是sda1, sda2。这就是backing device的概念。sda是sda1上ext4, sda2上fat的backing device,sda1和sda2的writeback都应该由backing device:sda的writeback thread来完成。
   bdi的全称是backing device info。它代表了一个backing device。每个文件系统在mount的时候,它的backing device就被记录到super->s_bdi中。如果backing device是个block device,那么其inode所在的backing device被记录到super->s_bdev->bd_inode->i_mapping->backing_dev_info中。Super和文件数据可以在不同的backing device上。对于block device,在block device创建的同时就创建了一个backing device info,基于该block device的文件系统在mount的时候将该backing device info链到自己的super和 inode的backing_dev_info。对于不在block device上的文件系统,如 FUSE,NFS等,是在mount的时候创建一个单独的backing device info ,这个backing device并不是一个实际的device,只是一个虚拟的writeback的主体。此外,在init的时候,会创建一个default backing device info,文件系统可以不必创建自己单独的 backing device info,直接使用default backing device info 。

   下面这张图全面展示了writeback的工作机制,接下来的章节我们将逐一讲述。

  • bdi的init, register

上节已经讲过default bdi在sys init时创建,而每个block device在创建的时候或每个文件系统在mount的时候可以创建自己单独的bdi。创建一个bdi主要包含以下步骤:

(1). 在bdi_init中:

*  创建一个struct backing_dev_info的变量来代表一个bdi。

*  创建一个work queue: bdi_wq用于存放writeback的事件。

* 创建一个delayed work(即bdi->wb.dwork)的thread,这个thread负责完成writeback动作。

(2). 在bdi_register中:

* 将这个bdi链接到全局变量bdi_list所指的bdi list里

default bdi和其他bdi的创建都是遵循了以上四个步骤,下面分别讲述。
  • default bdi的init, register
下图是在kernel init时default_bdi_init的流程,default bdi由default_backing_dev_info这个全局变量来代表。除了default_backing_dev_info之外,还创建了一个noop_backing_dev_info,它用来代表没有writeback需要。
  • block device (scsi disk) bdi的init, register
Block device的bdi创建过程和default bdi一样,只是backing dev info是在创建sda的request queue的时候同时创建的。请注意backing dev info是跟着sda的,不是sda1, sda2。
  • 从writeback queue到bio
  • Writeback thread

在第三章write()里面我们已经提到在__mark_inode_diry()里dirty的inode被移到writeback queue: bdi->wb.b_dirty里。这里我们将说明writeback queue的dirty inode的dirty page是怎样变成bio的。
首先,我们从writeback thread启动开始。从前面的图中我们已经知道,writeback thread是在bdi_init()时创建的一个delayed work,即bdiX->wb.dwork。当bdiX->wb.dwork->timer expire时,writeback thread的函数bdi_writeback_workfn()就开始运行,它的流程如下:

注意writeback的优先级顺序,先是强制writeback的work,如用户执行了fsync(fd),然后是writeback interval到了之后的work,最后是background的work。'work'是writeback的‘单位’,不管是sync()还是dirty_writeback_interval时间到了的writeback,都要包装成一个'work'交给writeback thread。

  • 一个'work'的Writeback过程

wb_writeback()函数负责完成一个work的writeback,下图是其流程。

一般一个文件系统mount的时候会有一个super block,对于文件系统层面的sync产生的writeback work,它的super block即work->sb是确定的。对于dirty_writeback_interval时间到了产生的work,所有在该bdi上的super block的dirty inode都要writeback,work->sb就不能指定了。典型的场景是sda1上有一个文件系统,sda2上有另一个文件系统,它们只有一个bdi。当只sync sda1的时候,产生的work->sb指定为sda1的super block,调用writeback_sb_inode()。当interval时间到了,sda bdi上所有的dirty inode都要sync,此时产生的work->sb就不能指定了,调用__writeback_inodes_wb()。实际上在__writeback_inodes_wb()内部还是遍历每个inode,软后调用writeback_sb_inode()的。所以writeback_sb_inode()是核心函数,下图是它的流程,因为比较长,我画了两页图。简单的说,就是一个一个writeback dirty inode,由__writeback_single_inode() 完成,直到这次writeback的时间到了或者没有dirty inode了。wbc是writeback control,用来控制writeback的。

writeback_sb_inode()的流程(图1):

writeback_sb_inode()的流程(图2, 接图1):


下面是__writeback_single_inode()的流程,其本质是通过实际文件系统实现时注册的address_space_operations的writebackpages() 或writbackpage()将dirty的Page写到media上,如果inode本身也是dirty的(比如文件的meta data, size等也改变了),那么这些文件信息也要写回media。


下面是ext2里aops->writeback的流程,本质是在实际文件系统的格式里找到要写page对应的block位置,构建出相应的buffer head(bh)以及bio,然后调用submit_bio()来产生一个对block device的write。

至此,我们已经讲完了dirty inode从writeback queue到bio的过程。bio还只是一个抽象的读写block device的请求,bio要变成实际的block device access还要通过block device driver,还要再排队,还要受到ioschduluer的控制。这些将在第五章讲述。

read()/write()的生命旅程之四——第四章:writeback相关推荐

  1. 生命旅程中何生命个体

    佛家云:"苦海无边,回头是岸."放弃对功名利禄的追逐,你随遇而安得到的将会是宁静与淡泊:放弃对金钱无止的掠夺,你安常处顺得到的将会是安心与快乐:放弃掌声鲜花的陶醉幸福,你激流勇退得 ...

  2. PX4模块设计之四十四: bmp280模块

    int bmp280_main(int argc, char *argv[]); PX4模块设计之四十四: bmp280模块 1. bmp280模块简介 2. 模块入口函数 2.1 主入口bmp280 ...

  3. 选对池塘钓大鱼([美]雷恩·吉尔森)第四章 想钓什么鱼?发现自己内在的需求...

    第四章 想钓什么鱼?发现自己内在的需求 如果能善加利用自己的欲望,包括完成工作的欲望和达成目标的欲望,或者二者兼备的欲望--就相当于拥有了驱动引擎的燃料.当然,这并不是无法中断的引擎--没有什么事情是 ...

  4. C++ API 设计 09 第四章 设计

    第四章 设计 上个章节是为开始设计API打下基础和准备必要的开发背景知识.我分析了各种对API设计有益的品质和讲解了应用于可维护的API设计的标准设计模式. 本章将把这些信息全部整合到一起,涵盖高品质 ...

  5. 走向.NET架构设计—第四章—业务层分层架构(后篇)

    走向.NET架构设计-第四章-业务层分层架构(后篇) 前言: 在上一篇文章中,我们讨论了组织业务逻辑的模式:Transaction Script和Active Record,Domain Model. ...

  6. 第四章,简答题4-5,2017-4-6

    巫师属性类------- 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System ...

  7. 人工智能:第四章 计算智能(1)

    第四章 计算智能(1) 教学内容:本章讨论计算智能所涉及的领域和范围,计算智能的含义及它与传统的人工智能的区别.介绍人工神经网络的由来.特性.结构.模型和算法:神经网络的表示和推理.简要地介绍模糊数学 ...

  8. Prism4文档翻译(第四章 第一部分) 转载bluesky234

    本节导读: 第四章介绍了模块化应用程序开发所必要的知识和需要注意的内容.而本部分通过讲述模块化应用程序开发所注意的必要概念,包括IModule接口,模块加载过程,模块列表,模块间通信,和依赖注入容器, ...

  9. 山海演武传·黄道·第一卷 雏龙惊蛰 第二十二 ~ 二十四章 真龙之剑·星墟列将...

    山海演武传·黄道·第一卷 雏龙惊蛰 第二十二 ~ 二十四章 真龙之剑·星墟列将 "我是第一次--请你,请你温柔一点--"少女一边娇喘着,一边将稚嫩的红唇紧贴在男子耳边,樱桃小嘴盈溢 ...

  10. IT项目管理总结:第四章 项目综合管理

    第四章 项目综合(Integration)管理 什么是项目综合管理 –它涉及在整个项目生命周期中协调所有其他项目管理的知识领域 –主要包括以下六个主要过程: A)制定项目章程(project char ...

最新文章

  1. MLIR: 编译器基础架构重定义
  2. java中ajax概念_Java之AJAX概念和实现方式
  3. list对oracle结果集排序了_MySQL之排序分组优化
  4. PHP获取优酷视频FLV地址
  5. 线程池的开源实现(mariadb和percona版本)
  6. jsp页面div上下滑动_H5单页面手势滑屏切换原理
  7. 邵阳市工业学校计算机29班,邵阳市南门口大祥区沙子坡文明路11号计算机学校...
  8. python列表推导式生成随机数_Python:列表推导式/生成器推导式
  9. 在阿里云容器服务中使用定时任务
  10. 在C++ Builder6上使用Boost正则表达式库
  11. Angular 4.0 安装组件
  12. mybatis使用详解
  13. 日期插件-jeDate
  14. Android APK 反编译工具 JADX
  15. 小学英语与计算机技术整合,信息技术与小学英语课程整合初探
  16. 25个常用Matplotlib图的Python代码,干货收藏!
  17. 阿里云服务器配置DNS域名解析
  18. knn代码实现+可视化
  19. 网络安全论文投稿给电脑编程技巧与维护有哪些要求
  20. flash人物原地走路_flash如何做人物走路

热门文章

  1. SQL 2005 带自增列 带外键约束 数据导入导出
  2. Xml序列化和反序列化对象-使用MemoryStream-实践
  3. MessageBox.Show常用的2个方法
  4. MySQL终端(Terminal)命令基本操作(转)
  5. 0903 - Firebase Analytics PK Google Analytics
  6. VC和gcc在保证功能static对线程安全的差异变量
  7. mysql 的 sql 语句的机读顺序
  8. centos 6.8 配置csh的shell和环境变量
  9. 携程android app插件化
  10. redis用zookeeper实现自动主从同步,切换