当前课程知识点:Linux 内核分析与应用 > 第8章 文件系统 > 8.4 页高速缓存机制以及读写 > Video
大家好下面我们来开始讲文件系统的第四讲
页高速缓存以及读写
那么文件系统的读写单位是什么呢文件系统的读写单位是块
一个块的大小是多少呢一个块的大小是2的n次方个扇区
比如说1k 2k 4k或者4M 等等
我们来看一下一个进程从发出读写请求到
读到数据一个简要的过程 如图所示
当用户通过write系统调用呢
给文件中写数据的时候呢首先呢
与用户态的I/O缓冲区打交道
然后逻辑文件中的写指针进行移动
那么真正的写入其实还没有发生
然后就陷入到内核态
那么用户态缓冲区的数据呢就
被搬到内核态缓冲区中
这个缓冲区就是page cache
到最后到底是如何把数据真正写入磁盘我们继续探究下去
我们看一下从buffer cache到page cache
buffer cache是面向底层块设备的
所以它的粒度是文件系统中的块
块设备和系统采用块进行交换
块再转换成磁盘的基本物理结构扇区
扇区和块之间是可以快速转换的
这就涉及到页高速缓存
随着内核的功能越来越完善
块粒度的缓存已经不能满足性能的需要
内核的内存管理组件
采用了比文件系统的块更高级别的抽象-页(page)
页的大小一般从4KB到2MB,粒度更大
处理的性能更高所以
缓存组件为了和内存管理组件更好地交互
创建了页缓存
page cache来代替原来的buffer cache
页缓存是面向文件面向内存的
通过一系列的数据结构比如inode
address_space, page将一个文件映射到页的级别
通过page + offset呢
就可以定位到一个文件的具体位置
下面我们来描述一下
页缓存的主要数据结构address_space对象
这里给出了这个数据结构的
源代码中的主要域以及相应的解释
我们可以看到其中第一个字段是host
每一个所有者可以理解为一个具体的文件
也就是一个inode指向的文件
它对应着一个address_space对象
页高速缓存的多个页可能属于一个所有者
从而可以链接到一个address_space对象
那么一个页(page)怎么和一个address_space
产生关联的呢
我们给出page对象
这个数据结构中有两个字段
mapping和index其中mapping指向该页
所有者的address_space
index字段表示所有者地址空间中
以页大小为单位的偏移量
用这两个字段就能在页高速缓存中
进行查找
那么索引节点页
或页缓存之间到底是什么样的关系呢
我们首先看一个inode节点对象呢
对应一个address_space对象
其中inode节点对象的
i_mapping和i_data字段
指向相应的 address_space对象
而address_space对象的host字段呢
指向对应的inode节点对象
每个address_space对象对应一颗基树
他们之间的联系是通过address_space对象中的
page_tree字段指向该
address_space对象对应的基树
一般情况下一个inode节点对象
对应的文件或者是块设备呢
都会包含多个页面的内容
所以一个inode对象对应多个page描述符
同一个文件拥有的所有page描述符呢
都可以在该文件对应的基树中找到
那么它们之间的关系呢如图所示
那么如何读取一个文件我们给出一个例子
假设一个进程reader要读取一个my.dat文件
实际发生的步骤如下
首先reader进程向内核发起读文件的请求
内核根据所读文件的inode呢
找到对应的address_space
在address_space中查找页缓存
如果没有找到数据
那么分配一个内存页加入到页缓存中
从磁盘中读取该文件相应的页呢
且填充页缓存中的页也就是第一次复制
然后呢从页缓存的页
复制内容到
reader进程堆空间的内存中也就是第二次复制
最后呢最后物理内存的内容就是这样的
同一个文件my.dat的内容呢
存在在两份拷贝中
一份是页缓存一份是用户进程的
堆空间对应的物理内存
下面呢我们来说一下如何写入文件
文件的读过程了解以后
我们继续来看文件的写入
从用户态来看文件的写入
与读取操作函数原型非常的相似
只是数据的流向不一样
从内核的角度来看
写文件对应的系统调用服务例程为sys_write
其对应的与读取的数据处理流程
基本上是相似的
只是将相应的函数中的read改为了write
对于写操作Linux同样采用了缓存技术
但这里的缓存跟文件读取用到的有些不一样
对于文件的写入考虑到一页数据页中呢
可能只是某一块数据发生了改变
这里写的过程结合了块缓冲技术
也就是说如果发现了脏页只是把
发生写入的脏块回写到磁盘即可
如图所示Write系统调用并不等数据
写入磁盘后才返回
这里Linux采用的是延迟写技术也就是说
当write把数据写入到
页高速缓冲的时候呢
write系统调用将此页标识为脏页
就返回到用户态了
而具体的脏页何时写入磁盘
内核有其他的机制负责写入
内核利用线程pdflush
更新页缓冲中的数据到磁盘
提供相应的系统调用比如sync这样的系统调用
由用户显式地通知内核写回未同步的数据
前边我们通过
写操作和读操作呢把整个的流程简要的概述
那么下面我们给出参考资料
依然是大家深入钻研
深入理解Linux内核 第三版
第十二章第十八章
深入Linux内核架构的第八章
最后大家带着疑问上路
请分析从一个文件读取数据的过程
page cache到底起什么样的作用大家一定要
亲自去读源代码亲自去感受 好 谢谢大家
-1.1 Linux操作系统概述
-1.2 Linux内核结构以及内核模块编程
--Video
-1.3 Linux内核源码中的双链表结构
--Video
-1.4 源码分析-内核中的哈希表
--Video
-1.5 动手实践-Linux内核模块的插入和删除
--Video
-第1章 概述--章节测验
-2.1 内存管理之内存寻址
--Video
-2.2 段机制
--Video
-2.3分页机制
--Video
-2.4 动手实践-把虚拟地址转换成物理地址
--Video
-第2章 内存寻址--章节测验
-3.1 进程概述
--Video
-3.2 Linux进程创建
--Video
-3.3 Linux进程调度
--Video
-3.4 动手实践-打印进程描述符task_struct中的字段
--Video
-3.5工程实践-基于内核模块的负载监控
--Video
-第3章 进程管理--章节测验
-4.1 Linux内存管理机制
--Video
-4.2 进程用户空间管理机制
--Video
-4.3 物理内存分配与回收机制(上)
--Video
-4.4 物理内存分配与回收机制(下)
--Video
-4.5 动手实践-Linux内存映射基础(上)
--Video
-4.6 动手实践-Linux内存映射实现(中)
--Video
-4.7 动手实践-Linux内存映射测试(下)
--Video
-4.8 初学者对内存管理的常见疑惑
-第4章 内存管理--章节测验
-5.1 中断机制概述
--Video
-5.2 中断处理机制
--Video
-5.3 中断下半部处理机制
--Video
-5.4 时钟中断机制
--Video
-5.5 动手实践-中断上半部的代码分析及应用
--Video
-5.6 动手实践-中断下半部的代码分析及应用
--Video
-第5章 中断--章节测验
-6.1 Linux中的各种API
--Video
-6.2 系统调用机制
--Video
-6.3 动手实践-添加系统调用(系统调用日志收集系统)
--Video
-第6章 系统调用--章节测验
-7.1 内核同步概述
--Video
-7.2 内核同步机制
--Video
-7.3 动手实践-内核多任务并发实例(上)
--Video
-7.4 动手实践-内核多任务并发实例(下)
--Video
-第7章 内核同步--章节测验
-8.1 虚拟文件系统的引入
--Video
-8.2 虚拟文件系统的主要数据结构
--Video
-8.3 文件系统中的各种缓存
--Video
-8.4 页高速缓存机制以及读写
--Video
-8.5 动手实践-编写一个文件系统(上)
--Video
-8.6 动手实践-编写一个文件系统(中)
--Video
-8.7 动手实践-编写一个文件系统(下)
--Video
-第8章 文件系统--章节测验
-9.1 设备驱动概述
--Video
-9.2 I/O空间管理
--Video
-9.3 设备驱动模型
--Video
-9.4 字符设备驱动程序简介
--Video
-9.5 块设备驱动程序简介
--Video
-9.6 动手实践-编写字符设备驱动程序
--Video
-9.7工程实践-编写块设备驱动的基础(上)
--Video
-9.8 工程实践-块设备驱动程序分析(中)
--Video
-9.9 工程实践-块设备驱动程序实现(下)
--Video
-第9章 设备驱动--章节测验
-致谢与说明
--Video