关于linux0.11文件系统高速缓冲的见解【《linux内核完全注释》阅读笔记】
阅读原文时间:2021年04月20日阅读:1

关于linux0.11文件系统高速缓冲的见解

以下内容截选自《Linux内核完全注释(修正版v3.0)》第12章文件系统。

以上是书中完整的对高速缓冲基本概念的说明。接下来小编我挑选其中一些代码进行进一步的论述。通过以上的基本概念的阅读,我们知道minix文件系统对高速缓冲块进行了两种方式的组织,一种是一个空闲项的双向循环链表,另一种是以设备号dev和块号block为关键特征的哈希散列表。

**
**

到这里高速缓冲块管理方面的代码基本就都实现了,首先我们就看看上面这个释放缓冲块的函数brelse,细心的你一定发现为什么这里没有把缓冲块回收到空闲循环链(freelist)中去呢?很明显,这里只是把引用计数减去了1.然后,再往上一点,我们看到移出队列(remove_from_queues)和插入队列(insert_into_queues)操作都是在获取缓冲块(getblk)函数中完成的。难道不回收到freelist,显然我们对于一般意义上空闲队列freelist的理解在这里是不适用的。其实这里minix在管理高速缓冲区的时候,所谓的空闲队列中的项并不一定都是空闲的,换言之,应该说是队列中引用计数为0的项都是空闲的,另外,我们还应该注意到的是在调用getblk的时候,我们在确认到某一块可能引用计数为0的缓冲块bh以后,移出和插入操作都是在这里一次性完成的。首先我们在remove_from_queues中将bh从原来的hash散列组中移出,并从freelist队列中移出。然后我们修改了这个被孤立后的bh的设备号dev和逻辑块号block,根据新的dev和block立马在insert_into_queues中将其插入到了新的hash散列组,并重新插入了freelist的尾部。这样我们也就间接保证了最新被使用的缓冲块出现在freelist的尾部,而最先被使用的缓冲块则出现在其头部。

如下为缓冲块初始化函数(buffer_init),双向循环链表freelist从这里开始实际在文件系统中就已经被分配好了完整的空间。后面的所谓释放和获取实际上是属于静态的操作,而不是动态。因为它只是去修改了一个所谓的占用标识而已。

接下来我们再看看在bitmap.c中对于申请一个逻辑块的操作函数(new_block),这里关于逻辑块位图的操作我们不讲,小编我这里还是重点说说关于高速缓冲块的操作。你会发现我们再通过getblk获取到该高速缓冲块后,只是做了一些修改标识和清除块内容的操作,便立即又调用brelse函数把他释放了。照以往对于程序的理解,这两步应该互为逆操作,同时依次调用,会被理解为什么都没有做,但是如前所述,这里针对引用计数这个变量来说,或许可以算是什么都没有做,但是在getblk的同时,别忘了,我们实际还完成了将对应这个dev和block插入到缓冲块bh所对应的新的hash散列组的操作,而这部分并没有被所谓的逆操作。因此在后续我们可能调用buffer.c中bread进行读取操作时,getblk通过已存在于hash表中的该高速缓冲块,便可以立刻在高速缓冲区中重新获取到该被“释放”的bh,并置其引用计数标志,以表示进程正在对其进行读操作。