(莱昂氏unix源代码分析导读-35)缓存管理(上)

                                                                               by cszhao1980

系统定义了NBUF个缓存区域,每个514个字节:

4720: char buffers[NBUF][514];

 

【注】:514个字节稍稍大于一个物理盘块的size,多出的2byte的用途不明。

 

而“缓存头”数组buf[NBUF]的每个entry对应一个缓存区域,其b_addr被设置为对应的缓存区

的首地址,如:&buffers[1]。对于缓存的使用都是通过其缓存头数组entry来完成。

 

【思考题】:为什么这里可以直接使用逻辑地址,如:&buffers[1]

 

Unix使用两种(带头结点的)双向循环链表(队列)来管理这些缓存,即

(1)         AV队列:即空闲队列,对首为buf bfreelist

(2)         B队列:即设备的任务队列,对首为某设备(devtab类型)。

                显然,可以有多个b队列。

(莱昂氏unix源代码分析导读-35)缓存管理(上)_第1张图片

【注】:在b队列当中,对首是devtab类型,而成员都是buf类型。该链表得以形成的原因是两种类

型都用同名的成员(b_forwb_back)作为前后指针,而且,它们的这两种struct中的位置是相同的。

 

总的原则是,空闲的缓存将挂在AV队列中,当需要操作某设备时就从AV队列中取下,挂到该

设备的b队列中,而设备操作完成后,又重新将其放还到AV队列中。

 

系统的某些实现使这一过程显得有些晦涩:

(1)         在设备操作完成后,会将缓存放回到AV队列,但没有将该缓存从原设备的b队列中取

下来——这一步是在再次分配该缓存时完成的。即在分配缓存时,分为3

i.           AV队列中取下;

ii.          从原设备队列中取下;

iii.        挂到新设备队列中。

 

(2)         问题来了,在系统初启阶段,所有缓存都没有分配过设备,那么其“原设备队列”在哪?

                 为解决这一问题,系统定义了一个特殊的设备队列——空闲设备队列,其设备号为-1,其

                  首指针为我们的老朋友buf freelist

 

之所以会采用这样的设计,是为了支持“延迟写”技术,以提高效率。所谓“延迟写”即写入缓存

的内容不会马上被写入磁盘——真正的写入是在用户程序或“定时”程序调用flush时完成的。

(1)         要支持“延迟写”,缓存必须仍挂在设备队列中,否则磁盘内容就会丢失;

(2)         如果直到真正写入后,缓存才可以释放回AV队列,有可能造成缓存资源紧张;

 

所以系统采用了这样的方式:

(1)         一旦对缓存的写入结束,该缓存即释放入AV队列,但其flag设置了B_DELWRI标志;

(2)         如果该缓存被再次分配,会检查器B_DELWRI标志,如其置位,则首先执行写入,再

                   将此缓存分配给新设备。

博客地址:http://blog.csdn.net/cszhao1980

博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html

你可能感兴趣的:((莱昂氏unix源代码分析导读-35)缓存管理(上))