当前课程知识点:Linux 内核分析与应用 > 第8章 文件系统 > 8.3 文件系统中的各种缓存 > Video
大家好今天我们来开始讲文件系统的第三讲
文件系统的缓冲区
那么什么是文件系统的缓冲区呢
我们说缓冲区它是内存空间的一个部分也就是说
在内存空间中预留了一定的存储空间
这些存储空间用来缓冲输入或输出的数据
这部分预留的空间就叫做缓冲区
如图中的红色框
在整个文件系统中有四种类型的缓冲区
dcache,inodecache,page cache,buffer cache
那么它们有什么样的作用呢有什么样的区别呢
下面我们来给予介绍首先我们来介绍一下
buffer和cache有什么样的不同
buffer是内存的缓冲区
是各进程产生的文件临时存储区
在一定的时间内会统一写入到磁盘
减少磁盘碎片或磁盘的反复寻道从而
提高系统性能简单来说buffer中的数据呢
就是要写入磁盘的数据
而cache也是内存的缓冲区是经常被用在
磁盘的I/O请求上
如果有文件频繁的被访问到呢
系统会将文件缓存在cache上
供cpu进程来访问
简单的来说cache中的数据就是
存放磁盘中读出来的数据
我们可以通过查看proc目录下的
meminfo文件看到你机子上
buffer和cache的大小
那么buffer cache和page cache有什么不同
page cache实际上是针对文件系统的
是文件的缓存在文件层面上的数据呢
会缓存到page cache中
文件的逻辑层需要映射到实际的物理磁盘
这种映射关系由文件系统来完成
当page cache中的数据需要刷新时呢
page cache中的数据就交给buffer cache
而buffer cache是针对磁盘块的缓冲
也就是在没有文件系统的情况
下直接操作的数据会缓存到buffer cache中
例如文件系统的元数据呢
都会缓存到buffer cache中如图中的橘色框
那么dcache和inodecache有什么样的作用
如图所示dcache是也就是dentry对象的cache
用于把路径转化为索引节点
inodecache也就是inode对象的cache
用于表示文件系统中的文件或者目录
下面我们来看一下打开文件到底是做什么
它跟我们所讲的缓冲有什么样的关系呢
打开文件的核心是查找
通常内核将查找过程分为两部分
第一个部分是查找根目录的信息
主要是判断是系统根目录还是当前的工作目录
以获取后面循环查找
起始位置这个位置指的是什么具体的文件系统
挂载位置以及从哪个目录开始
第二部分是循环查找路径名后续分量
以起始位置开始循环查找
后续的每个路径分量
下面我们对查找过程给一个概要的描述
查找过程看起来很简单但实际上内核实现还是比较复杂的
涉及众多cache技术
查找的关键接口为do_lookup
其主要过程如下
在dentry cache中查找相应的dentry
若找到则直接返回
若没有找到则必须去底层文件系统
查找对应的dentry
调用文件系统对应的inode_operations
操作集的lookup函数进行查找
首先在inode cache中查找是否
存在对应inode
如果有则返回如果没有则
必须去更底层的磁盘
查找对应的inode信息
去磁盘查找inode信息时
首先去buffer cache层
查找相应的块如果有相应的块存在
则从相应的buffer cache中提取inode信息
并将其转化为对应的文件系统的inode的结构
那么目录项缓冲是如何组织和查找的呢
由于块设备速度比较慢
可能需要很长时间才能找到与一个文件名
关联的inode信息
所以呢要引入dentry cache
那么缓存的组织呢
包括哪些部分呢有两个部分一个是散列表
它包含了所有活动的dentry对象
散列表由dentry_hashtable组成
dentry通过d_hash字段链入散列表中
第二个呢是一个LRU链表
Dentry结构中由d_lru链表组织
另外一个就是在缓存中如何进行查找
缓存由d_hash计算散列表
通过值对应的索引从dentry_hashtable中呢
查找对应的队列
再从队列头循环查找对应的dentry
也就是先从哈希表中查找
然后从LRU表中查找
那么下面我们来看一下索引节点缓存的组织和查找
同样为了加速查找引入了
索引节点缓存 也就是inode cache
索引节点缓存由inode_hashtable组织如图所示
下面我们来介绍一下buffer cache技术
如果要查找的inode不在inode cache中呢
这个时候呢需要从磁盘读取数据
就涉及buffer cache技术
buffer cache应用于经常按块读取的元数据
例如在查找过程中为了获取inode的信息呢
需要首先从磁盘读取super block的信息
buffer cache如何进行组织的呢
它的组织采用LRU链表如图是源码截图
其中bhs是一个缓冲头指针的数组
是用作实现LRU算法的基础
内核使用DEFINE_PER_CPU为每个CPU呢
都建立了一个LRU实例
以改进对CPU高速缓存的利用率
LRU缓存操作接口呢
我们这里给出两个一个叫lookup_bh_lru
去查找所需数据项是否在块缓存中
第二个lh_lru_install将新的缓冲头添加到缓冲中
下面我们讲一下Buffer cache 的头数据结构
这个数据结构把内存中的页
与磁盘中的块关联了起来
这里呢我们给出了源代码的截图
在源代码中对每个具体字段给予了解释
那么下面我们来给出 ext2文件系统超级块的组织形式
内核通过buffer cache技术呢
获取inode信息之前
我们首先看一下ext2文件系统超级块的组织形式
如图所示任何ext2分区中的第一个块呢
不受ext2文件系统的管理
因为这一块是为分区的引导扇区所保留的
ext2分区的其余部分被分割成块组(block group)
每个块组的分布图如图所示在ext2文件系统中
所有块组大小相同并被顺序存放
因此内核可以从块组的整数索引
很容易地得到磁盘中一个块组的位置
关于ext2的详细介绍请看维基百科
内核如何从磁盘获取inode信息
这里给出了源代码的截图
从这个源代码里头我们可以看出
首先根据索引节点号计算出它所在的块组
并得到该块组的描述符
然后算出其在块组索引
表中的偏移量并算出对应的块号
获取原始inode信息的过程需要读取超级块的信息
及具体实现在sb_bread函数中
其实现过程概述如下
通过参数包括块设备描述符
块号以及索引去buffer cache组织的
LRU链表中进行查找
如果缓冲区首部在LRU块高速缓存中
则返回对应的buffer_head类型的缓冲区首部
如果不在则需要去页高速缓冲中查找
看是否是在页高速缓冲中
如果存在则返回页高速缓存中
对应的块缓存区所对应的缓冲区首部
我们在这里呢对基于
缓冲区的查找过程给一个简要的概述
下面对本讲给个小结
我们说当应用程序打开一个文件的时候呢
首先是要查找到这个文件
在查找的过程中呢
目录项缓存可以加速文件路径名的解析
索引节点缓存可以加速文件元数据的查找
而数据缓存也就是页缓存可以加速数据的查找
这个呢我们在下一讲会讲到
这些数据都通过文件系统呢
传递给块的I/O层
然后呢封装成I/O请求给驱动程序
驱动程序最终从设备上读取数据
那么这方面相关的内容我们在下一章
块设备这一节进行具体的讲解
下面我们来给出参考资料
刚才讲了很多的内容你可能说根本还没听懂是的
肯定没有完全的听懂
那你听到了什么这里相当于给出了索引
需要你花数倍的时间和精力去看相关参考资料
深入钻研
深入理解Linux内核 第三版第十二章第十八章
深入Linux内核架构第八章
以及一篇参考文献的链接
最后带着疑问上路给
给定一个文件名如何查找到相关的文件
请继续阅读open的源代码并说明
缓冲区到底起了什么样的作用
-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