用户态和内核态IO过程

  熟悉mysql和kafka的刷脏页流程后,都知道内存中的脏页不会立刻刷到磁盘,下面就细化下流程

  写操作:

    用户调用 fwrite 把数据写入 C 库标准 IObuffer 后就返回,即写操作通常是异
  步操作;

    数据写入 C 库标准 IObuffer 后,不会立即刷新到磁盘,会将多次小数据量相
邻写操作先缓存起来合井,最终调用 write 函数次性写入(或者将大块数据分解多次
write 调用)页缓存;

    数据到达页缓存后也不会即刷新到磁盘,内核有 pdflush 线程
在不停地检测脏页,判断是否要写回到磁盘,如果是则发起磁盘 I/O 请求。

  总结:用户进程内存页--->C库IObuffer--->操作系统的页缓存--->落盘

  注意:C标准库的I/O缓冲区也在用户空间 

  

clib buffer:clib buffer是用户态的一种数据缓冲机制,在启用clib buffer的情况下,数据从应用程序的buffer拷贝至clib buffer后,并不会立即将数据同步到内核,而是缓冲到一定规模或者主动触发的情况下,才会同步到内核;当查询数据时,会优先从clib buffer查询数据。这个机制能减少用户态和内核态的切换(用户态切换内核态占用一定资源)。

PageCache:PageCache是内核态的一种文件缓存机制,用户在读写文件时,先操作PageCache,内核根据调度机制或者被应用程序主动触发时,会将数据同步到磁盘。PageCache机制能减少磁盘访问。

  读操作:

    用户调用 fread 到 C 库标准 IObuffer 中读取数据,如果成功则返回,否则继
  续;

    到页缓存中读取数据,如果成功则返回,否则继续;    

    发起 I/O请求,读取数据后缓存 buffer 和 C 库标准 IObuffer 并返回。

    可以看出,读操作是同步请求。

  I/O请求处理: 通用块层根据 I/O请求构造个或多个 bio 结构并提交给调度层;

          调度器将 bio 结构进行排序和合并组织成队列且确保读写操作尽可能理想

          将一个或多个进程的读操作合并到起读,将一个或多个进程的写操作合并到一起写,尽可能变随机为顺序 (因为随机读写比顺序读写要慢),读必须优先满足, 而写也不能等太久 。 

  bio结构就是kernel中block I/O的基础容器,它是在”linux/bio.h”中被定义的。这个结构将当前激活的block I/O操作表示为一个segment的list。segment就是内存中一块连续的buffer

  

posted on 2020-11-04 12:19  MaXianZhe  阅读(741)  评论(0编辑  收藏  举报

导航