Xv6内核分析(十三)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2020年12月20日18:06:48 评论 609

buffer cache分析

1. buffer cache概述

Buffer cache是一个双向循环链表,用于缓存磁盘上的数据以提高性能。使用bread从磁盘上读取数据,使用bwrite将修改的数据写回磁盘,使用bread或者bwrite之后需要调用brelease来释放buffer cache结点。

buffer cache通过一个bcache全局结构体变量来描述:

Xv6内核分析(十三)

其中spinlock用来保护对buffer cache链表的访问,NBUF的值默认是30,其中struct buf是用来描述每一个buffer cache的:

Xv6内核分析(十三)

2. binit函数

binit函数主要是将31个buffer cache结构体初始化形成双向循环链表:

Xv6内核分析(十三)

Xv6内核分析(十三)

3. bread函数

bread函数返回一个磁盘扇区对应的buffer cache结构体,如果磁盘的内容已经被缓存,则直接返回该结构体,否则从磁盘上读取数据到一个空闲的buffer cache中,然后再返回此结构体。

Xv6内核分析(十三)

bread通过调用bget获取一个可用的buffer cache,bget内容如下:

Xv6内核分析(十三)

访问buffer cache链表之前需要通过bcache.lock锁住链表,bget通过两次链表遍历来寻找可用的buffer cache。

第一次遍历链表来寻找要申请的磁盘区号是否已经缓存在链表中,判断方法是检查每个buffer cache结构体中的dev和blockno是否和传入的一样,如果一样,表示此磁盘块内容已经被缓存。那么接下来就将此buffer cache结构体中的引用计数加一,然后释放链表访问锁,接着获取此buffer cache的睡眠锁,表示此buffer cache有进程在使用。注意第一次遍历是从head->next开始的,因为head->next的buffer cache是最近一次cache的缓存,其最可能就是要获取的buffer cache。

如果要读的磁盘内容没有被缓存,那么就需要进行第二次链表遍历,以寻找一个可用的buffer cache结构体。这次的遍历顺序从head->prev开始,因为head->prev的buffer cache是最近不被使用的buffer cache,其最有可能是空闲的。如果buffer cache的引用计数是0并且此buffer不是脏的,那么就表示此buffer cache是空闲可用的,接着讲dev和blockno记录在此buffer cache中,同时清除flag标志成员,引用计数变为1,因为这是第一次引用,同时释放链表访问锁,接着获取此buffer cache的睡眠锁,表示此buffer cache有进程在使用。

b->flags的B_DIRTY位是在磁盘驱动的中断函数中被清除的。也就是说如果一个Buffer cache是空闲的,那么这块buffer cache的数据一定是和磁盘上一样的。

从以上分析可以看出,bget正常返回时返回的是一个锁住的buffer cache结构体。

回到bread看看:

Xv6内核分析(十三)

获取到buffer cache结构体后,接着检查此buffer中数据是否有效,如果无效,那么就要从磁盘上读取数据了,通过iderw从磁盘硬件上读取数据。

从上面分析可以看出,bread返回的是锁住的带有有效数据的buffer cache结构体。

4. bwrite函数

bwrite很简单,就是将数据写回磁盘,但是有个前提条件就是,当调用bwrite时,此buffer cache一定要是锁住的状态。

Xv6内核分析(十三)

首先检查了本进程是否拥有buffer cache的睡眠锁,如果没有直接报错。接着将buffer cache的标志位设置为脏,表示此buffer cache的数据被改写,最后调用iderw将buffer cache中的数据写回磁盘。

5. brelse函数

brelse用于释放一个锁住的buffer cache:

Xv6内核分析(十三)

首先检查了本进程是否拥有buffer cache的睡眠锁,如果没有直接报错。然后将此buffer cache解锁,这时此buffer cache就可以被其他进程使用了。

接着将buffer cache的引用计数减一,如果引用计数为0,表示没有进程在使用这块Buffer cache了,所以需要将此buffer cache归还到链表中。归还方式是将此Buffer cahce结构体放入head->next,所以head->next后的Buffer肯定表示最近被使用的buffer cache。

gewenbin
  • 本文由 发表于 2020年12月20日18:06:48
  • 转载请务必保留本文链接:http://www.databusworld.cn/9488.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: