硬件缓存与数据缓冲区的差异硬件缓存由一种高速寄存器组成,主要解决CPU与RAM之间的速度差异问题。
数据缓冲区缓存(buffer )是一种通过软件解决文件系统和物理硬盘之间的数据同步的方法。
具体思想如下。
1、构建称为数据缓冲器缓存(简称缓存)的内部数据缓冲池(buffer pool )并存储要使用的数据。
2、写数据时,尽可能多的将数据长时间存储在缓冲池中,延迟导出到磁盘供以后使用
3、读取数据时,在缓冲池中查找是否有现有数据,然后从磁盘中读取,保存在缓冲池中,在缓冲池的数据缓冲区中缓存预读数据,可以同时访问UNIX特有的数据
缓冲区和缓冲区的第一个缓冲区池由多个缓冲区组成,每个缓冲区实际上由存储数据的存储区和标识该缓冲区的缓冲区的第一部分组成。
由于缓冲器的前端和数据存储器之间存在一对一的关系,所以通常将两者统称为缓冲器。
缓冲区是缓冲池中数据存储的基本单位。
缓冲池结构1,最近的最小使用(LRU )算法:
编程采用模块化和分层机制,尽量避免使用goto语句,程序跳少,适应“流水线”体系结构的系统
在特定时间段,程序在相对集中的空间(代码段)内运行,涉及的数据(广义)文件名、变量、指针、数组等)数量相对较少
当前使用的数据最有可能很快又投入使用,长时间未使用的数据最有可能很快就投入使用。
2、缓冲池设计基本原则:
将刚使用的数据尽可能长时间地保留在内存中,以便立即或在使用时在内存中找到;
需要腾出内存空间时,将长期未使用(即最近最低使用的数据)更换为磁盘。 这些数据最不可能立即使用。
3、空闲缓冲链表
核心维护一个空闲缓冲链表,它按最近使用的优先级排序。 空闲链表是一个从空闲缓冲链表开头的“双向循环链表”。 链表的开始和结束标记链表的头部。
4、空闲缓冲链表操作
获取任意空闲缓冲区
从可用缓冲区链表的表头位置卸下下一个可用缓冲区,后面的可用缓冲区依次向前移动。
释放空闲缓冲区
将包含此数据的可用缓冲区附加到可用链表的链端。 只有在此空闲缓冲区中的数据错误时才会卡在链头上。
获取包含指定内容的空闲缓冲区
从链表头开始找,找到后取下使用,用完后放在链条末尾。 如果系统继续从链头获取可用缓冲区,并将已使用的(包含数据的)缓冲区卡在链尾,则包含有效数据的缓冲区将向链表头移动。 链表开头的是“最近最低使用”的可用缓冲区。
5、空闲缓冲区分类
系统中总共设置了四个可用缓冲链表,根据缓冲区的用途配置在不同的可用缓冲链表中。 获取空闲缓冲区时,请勿逐一判断缓冲区内的内容。 这四个空闲链表如下。
0#空缓冲区链表——存储文件系统的超块
1#可用缓冲区链表——存储通常使用的数据块
2#可用缓冲区链表——存储延迟写入、无效数据或错误的内容
3#可用缓冲区链表——存储没有相应存储空间的缓冲区标头
如果一种类型的可用缓冲区不足,则核心会从另一个可用缓冲区链表中获取可用缓冲区。
6、缓冲区设置
如果核心需要可用缓冲区,则根据要加载的数据类型,从相应可用缓冲区链表的标头位置中移除下一个可用缓冲区,然后加载磁盘数据块。 根据与该数据块对应的设备号和块号对计算其混列号(散列、散列)值,并基于该混列号的值放入相应的混列链表的链头中。
7、缓冲池结构
由于具有相同hashno的缓冲区链接到同一hash链表,因此系统中有63个hash链表,每个链表链接hashno为0到62的缓冲区。 每个混列链表都是指向链表开头的双向循环链表,在搜索具有指定混列否值的缓冲区时,也会从相应混列链表的页眉位置开始按页脚方向进行搜索。 这63个哈希表构成数据缓冲区的缓存池,所有缓冲区都存储在缓冲区池内的链表中。
8、缓冲区的使用
如果要查找特定缓冲区,请根据hashno在相应的hash链表的标头中向后搜索一个。 如果找到,则直接使用,并移动到散列链的链头;
如果找不到,则从相应的空缓冲区链表的头中取出下一个空缓冲区,输入相应的数据,重新计算其hashno,并将其放置在新的hash链表的头中; 释放缓冲区后,缓冲区将保留在原始散列队列中,并连接到可用缓冲区链表的末尾。 申请缓冲区有两种方法。
要在hash链表中搜索缓冲区——
要在可用链表中搜索可用缓冲区——
9、进一步说明
缓冲区仅在空闲时位于哈希表和空闲链表中。 如果没有空的话,就只能在hash链表里了。
可用缓冲链表的缓冲区必须位于某个散列表中; 混列表缓冲区不一定位于空闲链上。 没有人会退出hash链表
的另一个空闲缓冲链表。 缓冲器池中的缓冲器数量是固定的,每个缓冲器在不同的时间存储不同的磁盘数据块并具有不同的哈希值,因此在不同的ha中
sh链表中。
缓冲区中的数据与某个磁盘数据块一一对应,这种对应有两个特点:
① 一个磁盘数据块在缓冲池中最多只能有一个副本;
② 缓冲区与数据块的对应是动态的,LRU数据块将被释放。
缓冲区的检索算法
1、申请一个缓冲区算法 getblk
根据缓冲池的结构,核心申请一个缓冲区分配个磁盘块时,可能出现的五种典型状况:
① 该块已在hash队列中,并且缓冲区是空闲的;
② hash队列中找不到该块,需从空闲链表中分配一个缓冲区;
③ hash队列中找不到该块,在从空闲链表中分配一个缓冲区时,发现该空闲缓冲区标记有“延迟写”,核心必须写出缓冲区内容到磁盘上,再重新分配一个空闲缓冲区;
④ hash队列中找不到该块,并且空闲链表已空;
⑤ 该块已在hash队列中,但该缓冲区目前状态为“忙”。
2、 释放一个缓冲区算法 brelse
唤醒等待缓冲区的所有进程
提高处理机的执行级别以封锁同级或低级的中断
将该缓冲区放到空闲队列的尾部(缓冲区有效)或头部(缓冲区无效)
降低处理机的执行级别以开放中断
3、读一个磁盘块 bread
由 getblk 算法申请一个可用的缓冲区
如果缓冲区中的内容有效,则直接返回该缓冲区
如果缓冲区中的内容无效,则启动磁盘去读所需的数据块
等待磁盘操作完成后返回
4、 读一个磁盘块并预读另一个磁盘块 breada
预读的前提:
程序是在一个有限的空间内运行,程序对数据的访问是可预见的。
预读的命中率:
不一定达到100%,但良好的系统结构和算法可使命中率达到较高的水平。
预读的结果:
放在缓冲池内,以免需要的时候再去启动磁盘读数据块。
5、写磁盘块 bwrite
启动磁盘驱动程序的写操作
如果是“同步写”,则本进程睡眠等待磁盘写操作的完成,磁盘写操作完成后,中断唤醒本进程,本进程释放该缓冲区并返回;
如果是“异步写”,则无需等待磁盘写操作的完成,将缓冲区放到空闲链表的表头,以便随后某个进程申请空闲缓冲区时,将其写到磁盘上去。本进程不再关心该缓冲区实际被写出的时间和结果,而直接返回去作其它事情。
事实上无论是同步写还是异步写,其根本区别在于本进程是否等待磁盘驱动程序完成操作后所发出的中断信号。
数据缓冲区高速缓冲的优缺点
优点:
提供了对磁盘块的统一的存取方法
消除了用户对用户缓冲区中数据的特殊对齐需要
减少了磁盘访问的次数,提高了系统的整体I/O效率
有助于保持文件系统的完整性
缺点:
数据未及时写盘而带来的风险
额外的数据拷贝过程,大量数据传输时影响性能