熟悉mysql和kafka的刷脏页流程后,都知道内存中的脏页不会立刻刷到磁盘,下面就细化下流程
写操作:
用户调用 fwrite 把数据写入 C 库标准 IObuffer 后就返回,即写操作通常是异
步操作;
数据写入 C 库标准 IObuffer 后,不会立即刷新到磁盘,会将多次小数据量相
邻写操作先缓存起来合井,最终调用 write 函数一次性写入(或者将大块数据分解多次
write 调用)页缓存;
数据到达页缓存后也不会立 即刷新到磁盘,内核有 pdflush 线程
在不停地检测脏页,判断是否要写回到磁盘,如果是则发起磁盘 I/O 请求。
总结:用户进程内存页--->C库IObuffer--->操作系统的页缓存--->落盘
注意:C标准库的I/O缓冲区也在用户空间
读操作:
用户调用 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