Skip to content

缓冲区管理

2026 大纲 五(二)1 缓冲区管理,属「设备独立软件」层。

一个每秒几十字节,一个每秒几十亿次

前面几节把设备的"杂"处理完了:控制器统一了形态、分层统一了调用、 驱动吃掉了差异、分配决定了给谁。只剩最后一件事没解决——慢。

I/O 控制方式确实让 CPU 不用干等了(中断、DMA), 但它只解决了"等的时候能不能干别的",没解决另外三处不匹配:

速度不匹配——键盘每秒吐几十个字符,CPU 每秒能处理几十亿次。 没有中间存放处,字符一来就得立刻有人接,接慢一点就丢了。

粒度不匹配——磁盘按块读写(一次 512 B 或 4 KB),而程序可能只想读 3 个字节。 没有中间存放处,读 3 个字节也得占着整整一块的传输时间。

时机不匹配——进程想写的时候设备也许正忙,设备准备好的时候进程也许还没读。

这三处都靠同一样东西化解:在中间放一块内存,叫缓冲区。 ⚠️ 要注意速度不匹配与粒度不匹配是两件独立的事—— 即使两边速度一样,粒度不同照样需要缓冲。

这一节的技术内容集中在算时间:单缓冲、双缓冲各花多久,这是本章唯一的计算题型。 两个公式看着差不多,但差别只在一处很具体的地方——M 期间挡不挡得住设备。 把这一处想清楚,公式不用背。

一、引入缓冲的四个目的

四个目的不是并列的四条,而是同一个矛盾的四个侧面:生产者(设备或 CPU)与消费者(CPU 或设备)在速度、粒度、时机三方面对不上。

目的具体矛盾缓冲区怎么化解
缓和速度不匹配CPU 速度远快于设备生产者不必等消费者就绪就能把数据放下
减少中断频率、放宽响应时限每来一个字符中断一次,CPU 被打断得太频繁攒够一批再中断一次
解决粒度不匹配设备按块吐、应用按记录取,或反过来一次产出可供分几次取,或攒几次凑成一次
提高并行性没缓冲时双方必须"面对面交接",谁先到谁等交接变异步:放下就走,取走就用

二、单缓冲与双缓冲

单缓冲:内存中设一个缓冲区。设备把一块数据传入缓冲区(T),OS 再把它送到用户工作区(M),CPU 在工作区上处理(C)。

三段时间各自占用了什么资源,就是公式的全部成因:T 期间缓冲区被设备占着;M 期间缓冲区仍被占着(数据还在往外搬),设备被挡在门外;C 期间缓冲区已经空了,设备可以装下一块——所以 TC 能并行,M 只能串行付一次。

单缓冲每块耗时=max(T, C)+M

双缓冲(又称缓冲对换):设两个缓冲区,设备装满 A 就转去装 B,OS 同时把 A 里的数据搬到工作区。关键变化是 M 不再挡住设备M 从"串行付出的固定开销"变成 CPU 侧流水线的一环,与 C 串在一起,整条 CPU 侧与设备侧并行。

双缓冲每块耗时=max(T, C+M)
单缓冲与双缓冲的逐拍时间表:谁占着缓冲区、周期从哪读出来(想看清搬出数据那段时间怎么挡住设备时展开)

取一组具体的数:T=8M=1C=5(单位 ms)。

单缓冲,连续三块:

时刻 (ms)缓冲区在做什么用户工作区在做什么
0 – 8第 1 块的 T:设备正往里写
8 – 9第 1 块的 M:往外搬,缓冲区仍被占着,设备进不来第 1 块的 M:正在接收
9 – 14第 2 块的 T:缓冲区一空设备立刻开工第 1 块的 C:CPU 处理
14 – 17第 2 块的 T 未完,继续空(C 只要 5 ms,比 T 短,先干完了)
17 – 18第 2 块的 M设备再次被挡在门外第 2 块的 M
18 – 23第 3 块的 T第 2 块的 C
23 – 26第 3 块的 T 继续
26 – 27第 3 块的 M第 3 块的 M

周期怎么读出来:看同一事件反复出现的间隔——第 1 块的 M 在 8,第 2 块在 17,第 3 块在 26,每块 9 ms,正是 max(8,5)+1

双缓冲,同一组数,A、B 轮流用:

时刻 (ms)缓冲区 A缓冲区 B用户工作区
0 – 8第 1 块的 T
8 – 9第 1 块的 M第 2 块的 T(设备没停)第 1 块的 M
9 – 14第 2 块的 T 继续第 1 块的 C
14 – 16第 2 块的 T 继续空(CPU 侧只要 6 ms,先干完了)
16 – 17第 3 块的 T(设备没停)第 2 块的 M第 2 块的 M
17 – 22第 3 块的 T 继续第 2 块的 C
22 – 24第 3 块的 T 继续

周期:第 1 块的 M 在 8、第 2 块在 16、第 3 块在 24——每块 8 ms,正是 max(8, 5+1)。8–9 那一行就是"OS 正对 A 做 M、设备同时往 B 里写",设备一刻没停,它是瓶颈。

把这组数推到 10 块,三种配置的总耗时:

配置每块耗时处理 10 块
单缓冲max(T,C)+M=max(8,5)+1=9 ms90 ms
双缓冲max(T,C+M)=max(8,6)=8 ms80 ms
8 个缓冲区的循环缓冲仍是 max(T,C+M)=8 ms80 ms,与双缓冲完全相同

三行各自的算法不同:单缓冲先比 TC 取大者(它俩能并行),再把 M 加在外面(它挡着设备,必须串行);双缓冲把 M 挪到 CPU 侧与 C 相加,因为设备此刻在写另一个缓冲区;第三行 T=8>C+M=6,设备是瓶颈,缓冲区再多也不能让设备变快,队列只会一直空着——"加到 8 个一秒都省不出来"这句话的证据就是这张表的后两行相等

换一组参数即可看出双缓冲也不总占优:T=2M=1C=9(CPU 慢)时,单缓冲 =max(2,9)+1=10 ms,双缓冲 =max(2,10)=10 ms,两者相等——CPU 侧是瓶颈,双缓冲省下的那次串行 M 已经被藏进 max 里了。

三、缓冲区数量 → 每块耗时的一般模型

单缓冲、双缓冲只是 n=1n=2 两个特例。把它当两级流水线看:设备侧每块花 T(占缓冲区),CPU 侧每块花 M+C

缓冲区数 n每块平均耗时为什么
n=1max(T, C)+M只有一个缓冲区,M 期间设备被挡在门外,M 只能串行付
n=2max(T, C+M)设备写另一个缓冲区,M 不再挡设备,两级完全并行
n2(循环缓冲、缓冲池)仍是 max(T, C+M)稳态吞吐由较慢那一级决定,加缓冲区不能让慢的那级变快

加缓冲区改善的是平滑度,不是稳态平均值

T>C+M,设备是瓶颈,再多缓冲区也只是排着队等设备;若 T<C+M,CPU 侧是瓶颈,缓冲区早就空着了。

多设缓冲区图的是抗突发:设备速率或 CPU 处理速率不稳定时,多缓冲区吸收波动,不让瞬时的慢拖住对方。教材的说法是——"当输入与输出的速度基本相匹配时双缓冲效果就够好,若两者相差甚远,可随着缓冲区数量的增加使情况有所改善"。改善的是平滑度。

四、循环缓冲(环形缓冲区)

把多个大小相同的缓冲区组织成环形队列,输入进程与计算进程各在环上追赶。

缓冲区类型含义对应指针指针指向
R(空缓冲区)可供输入进程装数据Nexti输入进程下次可用的空缓冲区 R
G(已装满数据)等待计算进程取用Nextg计算进程下一个可用的缓冲区 G
C(现行工作缓冲区)计算进程正在使用Current该缓冲区中正在处理的单元
  • Getbuf:计算进程调用时,把 Nextg 指的缓冲区交给它、改为现行工作缓冲区 C,Current 指向其第一个单元,Nextg 前移一格;输入进程调用时,把 Nexti 指的空缓冲区交给它,Nexti 前移一格。
  • Releasebuf:计算进程取完数据后调用,把 C 改回空缓冲区 R;输入进程装满后调用,把该缓冲区改为 G。

两个指针沿同一方向移动,会出现两种"撞车":

情形含义谁阻塞谁唤醒它教材叫法
Nexti 追上 Nextg输入快于计算,空缓冲区用光输入进程阻塞计算进程 Releasebuf 释放出空缓冲区时系统受计算限制
Nextg 追上 Nexti计算快于输入,装满的缓冲区被抽空计算进程阻塞输入进程装满某块调 Releasebuf 时系统受 I/O 限制

五、缓冲池

专用缓冲是为特定的一对生产者/消费者设的,系统一大就要开很多套,内存耗得多、利用率还低。于是引入既可输入又可输出的公用缓冲池

每个缓冲区由缓冲首部(缓冲区号、设备号、数据块号、同步信号量、队列链接指针)与缓冲体(存数据)组成。同类型的缓冲区链成队列,共三个;另有四种工作缓冲区:

操作(工作缓冲区)从哪个队列取用完挂到哪个队列
收容输入空白缓冲队列 emq → 装入输入数据输入队列 inq
提取输入输入队列 inq → CPU 取走处理空白缓冲队列 emq
收容输出空白缓冲队列 emq → 装入输出数据输出队列 outq
提取输出输出队列 outq → 送往设备空白缓冲队列 emq

数据结构里的 Addbuf(挂队尾)、Takebuf(摘队首)不能直接用:缓冲池里的队列本身是临界资源,多个进程会同时访问同一队列。为每个队列加互斥信号量 MS(type) 与资源信号量 RS(type),改造成:

Getbuf(type):Wait(RS(type)); Wait(MS(type)); B=Takebuf(type); Signal(MS(type));Putbuf(type, B):Wait(MS(type)); Addbuf(type, B); Signal(MS(type)); Signal(RS(type));

六、磁盘高速缓存与两级缓冲区

磁盘高速缓存指利用内存中的存储空间暂存从磁盘读出的数据;它不是 CPU 与主存之间的硬件 Cache,而是操作系统在内存里维护的磁盘数据副本。两种组织形式:

形式说明
固定专用缓存区在内存中开辟固定大小的区域,专门缓存磁盘数据
动态缓冲池利用系统空闲内存作缓冲池,供请求分页与磁盘 I/O 共享

用户缓冲区是用户进程自己申请的一块内存(如一个数组),每次 read 把数据填进去,处理完再发下一次 read——省的是系统调用次数。内核缓冲区由 OS 在内核空间维护:读命中就直接复制到用户缓冲区,未命中才发起磁盘 I/O 并挂起进程;写操作先落内核缓冲区,攒够一定量或满足刷新条件才批量写盘——省的是实际磁盘 I/O 次数。

公式里的 M 就发生在这两层之间

M(缓冲区 → 用户工作区)正是内核缓冲区到用户缓冲区那一次内存拷贝。它是分层的代价的量化体现,也是内存映射文件想要省掉的那一趟。

考点速记

  1. 缓冲区化解的是速度、粒度、时机三方面的不匹配。⚠️速度不匹配与粒度不匹配是两件独立的事——即使两边速度一样,粒度不同照样需要缓冲。
  2. 符号口径T设备把一块数据送进缓冲区的时间,M缓冲区到用户工作区的传送时间,CCPU 处理一块的时间。
  3. 单缓冲:每块平均耗时 max(T,C)+M 理由是 M 期间缓冲区被占着,设备不能往里送下一块,所以 M 必须单独加。
  4. 双缓冲:每块平均耗时 max(T, C+M) 理由是有第二个缓冲区,M 期间设备可以往另一个里送,所以 M 被并进 CPU 那一侧。
  5. ⚠️两个公式唯一的差别就是 M 期间挡不挡得住设备——记住这一句,公式不用背。
  6. n2 起公式不再变化,多缓冲区买的是抗波动而非更高吞吐。
  7. 缓冲池的队列是临界资源Getbuf 必须RS(资源信号量)后 MS(互斥信号量),顺序反了会死锁。
  8. 磁盘高速缓存与缓冲区的分界是"数据取走后还留不留":缓冲区取走即空出、留给下一批;磁盘高速缓存取走后仍留着,指望下次还命中。
  9. ⚠️设置磁盘缓冲区的主要目的是减少磁盘 I/O 次数——不是减少平均寻道时间(那是磁盘调度的事)、不是提高数据可靠性、也不是实现设备无关性(那是 LUT 的事)。
  10. 能改善磁盘 I/O 性能的手段:重排 I/O 请求次序(磁盘调度)、预读与滞后写(缓冲)、优化文件物理块的分布(减少寻道)。⚠️在一个磁盘上设置多个分区不能改善性能——分区只是逻辑划分,反而可能让访问跨区、寻道更远。

这一节在真题里被考过的形式

三道题:两道算时间,一道问缓冲的目的。 计算那一类是本章唯一的题型,必须练熟。

  • TMC 与块数,算单缓冲与双缓冲下读入并处理完的总时间(2011-31)。10 块,答单缓冲 1550 μs、双缓冲 1100 μs。⚠️ 两处容易错:最后一块要单独算(前 n1 块按稳态公式走,最后一块还要加上它自己的 M+C,不能直接乘 n);以及别把两个公式记混——差别只在 M 那一项的位置(速记第五条)。
  • 系统缓冲区与用户工作区均单缓冲,问读入并分析 2 个数据块的最短时间(2013-27)。这道题把两级缓冲串起来了,要按流水线排时间线,不能直接套单块公式乘 2。判据仍是速记第三条——每一级的 M 期间,它上游的那一级都被挡住了
  • 问在系统内存中设置磁盘缓冲区的主要目的(2015-28)。答减少磁盘 I/O 次数。⚠️ 另三项各自属于别的机制:减少平均寻道时间是磁盘调度算法干的、提高数据可靠性靠的是冗余与校验、实现设备无关性靠的是逻辑设备表。
  • 问哪一项不能改善磁盘设备的 I/O 性能(2012-32,与磁盘结构与调度共享)。答在一个磁盘上设置多个分区。⚠️ 分区是逻辑划分,不改变任何物理特性;反而可能因为数据被分到不同分区而让磁头跑得更远。另三项都能:重排 I/O 请求次序、预读和滞后写、优化文件物理块的分布。

复习优先级必须拿满,且计算要练熟。 速记第三到五条是全部计算题的依据, 把"M 期间挡不挡得住设备"这一句想透就够了,不必分别背两个公式。 做题时盯死一处:最后一块要单独算。概念题只有第九、十条两句话。

易错:把单缓冲和双缓冲的公式记混。差别只在 M 期间设备能不能继续送——不能就单独加,能就并进 CPU 侧。

易错:算总时间时直接用公式乘块数。最后一块要单独加上它的 M+C

易错:认为缓冲区数量越多吞吐越高。n2 起公式就不变了,多的缓冲区买的是抗波动。

易错:认为设置磁盘缓冲区是为了减少寻道时间。目的是减少磁盘 I/O 次数;减少寻道是磁盘调度的事。

易错:认为在一个磁盘上分多个区能提升 I/O 性能。分区是逻辑划分,不改变物理特性。

易错:把磁盘高速缓存和缓冲区当成一回事。分界是数据取走后还留不留

易错:认为速度匹配了就不需要缓冲。粒度不匹配是独立的一件事

教材出处
  • 引入缓冲的四个目的、单缓冲区每块处理时间 max(C,T)+M 的推导与字符设备的行缓冲约定:汤小丹《计算机操作系统》6.7.1~6.7.2 节,印刷 p210
  • 双缓冲区(缓冲对换)与"粗略地认为是 max(C,T)"的口径、双机通信时的缓冲区设置:同书 6.7.2 节,印刷 p211
  • 环形缓冲区的三类缓冲区 R/G/C、三个指针 Nextg/Nexti/Current、Getbuf 与 Releasebuf 过程、两个指针互相追赶导致的两种阻塞:同书 6.7.3 节,印刷 p212
  • 缓冲池的组成(缓冲首部与缓冲体、emq/inq/outq 三队列、四种工作缓冲区)与 Getbuf/Putbuf 中互斥信号量 MS 和资源信号量 RS 的设置:同书 6.7.4 节,印刷 p213

相关知识

I/O 控制方式I/O 软件层次结构设备分配与回收磁盘结构与调度

真题练习

相关真题(3题)