缓冲区管理
目录
参考资料:
缓冲区是一个存储区域,它可以由专门的硬件寄存器组成,也可以由内存组成。
由寄存器组成的缓冲区较小,成本较高,一般仅用在对速度要求非常高的场合,如存储器管理中所用的联想存储器,设备控制器中用的数据缓冲区等。更多情况下,都是使用内存作为缓冲区。
1 单缓冲区和双缓冲区
如果在生产者与消费者之间未设置任何缓冲,生产者与消费者之间在时间上会相互限制。例如,生产者已经完成了数据的生产,但消费者尚未准备好接收,生产者无法把所生产的数据交付给消费者,此时生产者必须暂停等待,直到消费者就绪。如果在生产者与消费者之间设置了一个缓冲区,则生产者无需等待消费者就绪,便可把数据输出到缓冲区。
1.1 单缓冲区
当用户进程发出 I/O 请求时,操作系统便在主存中为之分配一个缓冲区。
由于缓冲区是共享资源,生产者与消费者在使用缓冲区时必须互斥。如果消费者尚未取走缓冲区中的数据,即使生产者又生产出新的数据,也无法将它送入缓冲区,生产者等待。
1.2 双缓冲区
为了加快输入和输出速度,提高设备利用率,又引入了双缓冲区机制,也称为缓冲对换(Buffer Swapping)。在设备输入时,先将数据送入第一缓冲区,装满后便转向第二缓冲区。
双缓冲区在两台机器之间的通信应用
如果两台机器之间的通信仅使用单缓冲区,那么它们之间在任一时刻都只能实现单方向的数据传输。例如,只允许把数据从 A 传送到 B 或者从 B 传送到 A,而绝不允许双方同时向对方发送数据。
半双工通信
为了实现双向数据传输,必须在两台机器中都设置两个缓冲区,一个用作发送缓冲区,另一个用作接收缓冲区。
2 环形缓冲区/多缓冲区
环形缓冲区由多个缓冲区的组成,其每个缓冲区的大小相同。其中的缓冲区可分为三种类型:空缓冲区 R、已装满数据的缓冲区 G 以及正在使用的缓冲区 C,如下图所示。
因此,环形缓冲区也包含多个指针。如,用于指示下一个有数据的缓冲区 G 的指针 Nextg,指示下次可用的空缓冲区 R 的指针 Nexti,以及用于指示正在使用的缓冲区 C 的指针 Current。
3 缓冲池(Buffer Pool)
当系统较大时,会有许多的循环缓冲区,这不仅要消耗大量的内存空间,而且其利用率不高。为了提高缓冲区的利用率,可以使用既可用于输入又可用于输出的公用缓冲池,在池中设置了多个可供进程共享的缓冲区。
缓冲池与缓冲区的区别在于:缓冲区仅仅是一组内存块的链表,而缓冲池则是包含了一个管理的数据结构及一组操作函数的管理机制,用于管理多个缓冲区。
3.1 缓冲池的组成
缓冲池管理着多个缓冲区,每个缓冲区由缓冲首部和缓冲体两部分组成。
- 缓冲首部:用于标识和管理缓冲区,一般包括缓冲区号、设备号、设备上的数据块号、同步信号量以及队列链接指针等。
- 缓冲体:用于存放数据。
为了管理上的方便,一般将缓冲池中具有相同类型的缓冲区链接成一个队列,于是可形成以下三个队列:
- 空白缓冲队列 emq。由空缓冲区所链成的队列。其队首指针 F(emg) 和队尾指针 L(emq) 分别指向该队列的首缓冲区和尾缓冲区。
- 输入队列 inq。由装满输入数据的缓冲区所链成的队列。其队首指针 F(ing) 和队尾指针 L(inq) 分别指向输入队列的队首和队尾缓冲区。
- 输出队列 outq。由装满输出数据的缓冲区所链成的队列。其队首指针 F(outq) 和队尾指针 L(outq) 分别指向该队列的首、尾缓冲区。
除了上述三个队列外,还应具有四种工作缓冲区:
- 用于收容输入数据的工作缓冲区
- 用于提取输入数据的工作缓冲区
- 用于收容输出数据的工作缓冲区
- 用于提取输出数据的工作缓冲区
3.2 缓冲池的工作方式
- 收容输入。从空缓冲队列 emq 的队首摘下一空缓冲区,作为收容输入工作缓冲区 hin。当缓冲区 hin 数据装满后,把它挂在输入队列 inq 队列上。//空队列->输入队列
- 提取输入。从输入队列 inq 的队首取得一缓冲区作为提取输入工作缓冲区 sin,从缓冲区 sin 中取完数据后,将它挂到空缓冲队列 emq 上。//输入队列->空队列
- 收容输出。从空缓冲队列 emq 的队首取得一空缓冲区,作为收容输出工作缓冲区 hout。当缓冲区 hout 装满输出数据后,将它挂在输出队列 outq 的末尾。//空队列->输出队列
- 提取输出。从输出队列 outq 的队首取得一装满输出数据的缓冲区,作为提取输出工作缓冲区 sout。缓冲区 sout 数据提取完后,将它挂在空缓冲队列末尾。//输出队列->空队列
// 缓冲池的工作,就是对三种队列的操作和转换过程。