文件系统的缓冲区

什么是文件系统的缓冲区呢?

我们说缓冲区,它是内存空间的一个部分也就是说在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。
在整个文件系统中有四种类型的缓冲区:

  • 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,用于把路径转化为索引节点inode。inodecache也就是inode对象的cache,用于表示文件系统中的文件或者目录。


我们来看一下打开文件到底是做什么,它跟我们所讲的缓冲有什么样的关系呢?
打开文件的核心是查找,通常内核将查找过程分为两部分:

第一个部分是查找根目录的信息,主要是判断是系统根目录还是当前的工作目录,以获取后面循环查找起始位置。这个位置指的是什么具体的文件系统,挂载位置以及从哪个目录开始。
第二部分是循环查找路径名后续分量,以起始位置开始循环查找后续的每个路径分量。

我们对查找过程给一个概要的描述:查找过程看起来很简单,但实际上内核实现还是比较复杂的,涉及众多cache技术。查找的关键接口为do_lookup,其主要过程如下:(1)在dentry cache中查找相应的dentry,若找到则直接返回;若没有找到则必须去底层文件系统查找对应的dentry;(2)调用文件系统对应的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 的头数据结构buffer_head。这个数据结构把内存中的页与磁盘中的块关联了起来。
内核如何从磁盘获取inode信息?首先根据索引节点号计算出它所在的块组,并得到该块组的描述符,然后算出其在块组索引
表中的偏移量并算出对应的块号。获取原始inode信息的过程需要读取超级块的信息。具体实现在sb_bread函数中。其实现过程概述如下:(1)通过参数包括块设备描述符,块号以及索引;(2)去buffer cache组织的LRU链表中进行查找;(3)如果缓冲区首部在LRU块高速缓存中,则返回对应的buffer_head类型的缓冲区首部;(4)如果不在,则需要去页高速缓冲中查找,看是否是在页高速缓冲中;(5)如果存在,则返回页高速缓存中对应的块缓存区所对应的缓冲区首部;

我们说当应用程序打开一个文件的时候,首先是要查找到这个文件。在查找的过程中,目录项缓存可以加速文件路径名的解析;索引节点缓存可以加速文件元数据的查找;而数据缓存也就是页缓存可以加速数据的查找;

这些数据都通过文件系统传递给块的I/O层,然后封装成I/O请求给驱动程序,驱动程序最终从设备上读取数据。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值