文章目录
- 第三章 数据缓冲区高速缓存
-
- 缓冲首部---buffer_head
- 缓冲池的结构
- 缓冲区的检索-getblk
- 读磁盘块与写磁盘块
- 高速缓冲的优点和缺点
- 习题
-
-
-
- 最好的散列函数是使块均匀分布在散列队列集合上的散列函数,什么是最理想的散列函数?在计算中应该使用逻辑设备号嘛?
- getblk中,摘下一个缓冲区时必须提高处理机优先级,以便在检查空闲表之前封锁中断,为什么?
- getblk中,检查一个块是否处于忙状态之前,必须提高处理机优先级封锁中断,为什么?
- 在算法brelse中,如果缓冲区内容无效,则核心把该缓冲区放入到空闲表队列头部,如果缓冲区内容无效,该缓冲区应该出现在散列队列中嘛?
- 假设核心进行一个块的延迟写,当另一个进程从它的散列队列中取出那个块时会发生什么?从空闲表呢?
- 重新设计getblk以保证一个进程最终能用上一个缓冲区
- umount与sync等几个不同的系统调用,请求将核心把对一个特定的文件系统“延迟写”的所有缓冲区都清理到磁盘上;描述一个实现缓冲区清理的算法;作为清理的结果,对于空闲表上的缓冲区次序发生了什么?核心怎么样才能保证当清理进程因等候一个IO完成而睡眠时,没有别的进程偷偷溜进来用延迟写的方法把一个缓冲区写到这个文件系统中?
- 把系统响应时间定义为它完成一个系统调用所占用的平均时间;把系统吞吐量定义为在一个给定时间段内系统所能执行的进程数目;描述高速缓冲能够怎么样有助于缩短响应时间;它必定有助于提高系统吞吐量嘛?
-
-
第三章 数据缓冲区高速缓存
对文件系统的一切存取操作,核心都能通过每次直接从磁盘上读或往磁盘上写来实现。但是慢的磁盘传输速率会使系统响应时间加长、吞吐率降低;因此,核心通过保持一个称为数据缓冲区高速缓冲的内部缓冲区池来试图减小对磁盘的存取频率,高速缓冲含有最近被使用过的磁盘块的数据。
高层核心算法让高速缓冲模块把数据预先缓存起来,或延迟写数据以扩大高速缓冲的效果!
缓冲首部—buffer_head
好吧,Linux中的buffer.c就是完全盗版的这本书里的数据结构和算法···,没话说,不过Linux还是有非常多的过人之处的;
Linus将上图中的状态分成了三个分量:lock, uptodate, dirt
缓冲池的结构
核心遵循的算法的是:最近最少使用算法,即在空闲表中选取缓冲区时要选择最近最少使用的缓冲区; 即空闲表会维护一个最近最少使用的次序,空闲表的开头一般是最近最少使用的缓冲块;
当核心把一个缓冲区还给缓冲区池时,它通常把该缓冲区附到空闲表的尾部;
另外一点就是散列表和散列函数:
散列表中对应的队列也是双向链表
散列队列中各个缓冲区的位置是不重要的,没有两个缓冲区可以同时包含一个磁盘块上的内容,因此,缓冲区池中的每个磁盘块存在且仅存在于一个散列队列中,并且仅在那个散列队列中呆一阵;然而,如果一个缓冲区为空闲状态,则它也可以在空闲表中;因为一个缓冲区既可在一个散列队列中又可在一个空闲队列中,所以核心有两个办法可以找到它;如果要找一个特定缓冲区,则从散列表中找,如果要找空闲缓冲区,则遍历空闲表;
一个缓冲区总是在某个散列队列上,但是它可以在或不在空闲表中;??? 那么初始状态呢?
说起来,如果不读本书,那么Linux代码可能很难理解透彻;
缓冲区的检索-getblk
getblk:将一个缓冲区分配给磁盘块,下面讨论五种情况:
1 该块在散列队列中,并且它的缓冲区是空闲的
将该缓冲区标记为忙,并将该缓冲块从空闲链表中摘下来;
用完之后会调用brelse,其会将该块放置到空闲表尾部,但是并没有把散列表中的指针破坏,也就是说如果再次调用了相同的getblk仍然可以找到该缓冲区,但是如果其他缓冲区不够用了,也可以将刚才释放的缓冲区拿去用;
2 散列队列中找不到,从空闲表中分配一个
注意从空闲表中找到的这个缓冲区也可能会在某个散列队列中,因为其曾经分配给另一个磁盘块;
这时候会将其链接到对应的散列队列中,也会改变其在空闲表中的结构,将其从空闲表中摘下来;