接下来,我们简单地回顾一下I/O缓冲(之前在ch5-4-1的时候有提到过)

背景:
假设进程I/O需要在灰色区间读写,而灰色区间由于阻塞而被对换出去了,此时OS找不到对应的内存地址,这样就容易发生死锁。所以为了避免上述问题,就要“提前输入,延迟输出”。
提前输入是一种数据处理技术,它预先从输入源(如硬盘、网络等)读取数据到一个临时存储区域(即缓冲区)。这样做的目的是减少等待时间和提高数据访问速度。通过预先加载数据,系统可以迅速地获取必要的数据,而不必在每次需要时才去源头读取,这通常涉及更高的延迟。
延迟输出是指将输出操作暂存到缓冲区中,而不是立即写入目标(如硬盘)。这允许系统合并多个输出操作为较少的、更大块的写入操作,从而减少对输出设备的访问次数。这种策略可以有效减少写操作引起的性能瓶颈,特别是在目标设备相对较慢的情况下。
一般来说,缓冲区是OS在内存中专门开辟的一个空间,并且缓冲区常驻内存。如果缓冲区为空,没有相关文件,就必须要到外设去读写。
缓冲的目的
注:物理记录相当于物理设备上的数据记录,而加载到缓冲区之后,就可以根据进程需要的内容传递相应的逻辑记录
缓冲区的等待
缓冲的分类:
这里的缓冲分类,对应我们的外围设备中的块设备和字符设备,接下来我们会具体讲不同缓冲区的特点。

需要提前读,但是每次只能读一块数据,这样到下次进程需要,直接从缓冲区取就行

C是calculate的简写,M是move,T是transfer
这里我们了解一下C,T,M的具体含义
对C和M进行比较,可以看出该进程的类型(如果 C >> M,是CPU型,反之是I/O型进程)
2. 基于字符流的单缓冲

字符终端,键盘/显示器一般是行缓冲(输入或者输出的过程中遇到换行符时,才执行真正的输入输出操作),某些特殊设备也可以基于字节缓冲

由于 M<< T,M 就忽略不计,实际上不一定满足
PS:当 M 不远小于 T 的时候,需要考虑 M 的时间,此时要放在 C 这边,即处理一个数据块的平均耗时是 Max(T, C+M)

e.g., Linux中的循环缓冲

这张图片是关于早期 Linux 系统(特别是 LINUX 0.1X 版本)的内存管理和启动过程的视觉说明。图中详细展示了系统内存从 0 到 16M(兆字节)的分配和利用情况

空闲列表具体实现使用的是结构体数组,通过指针串成了双向的循环列表,每一个结构体有一个指向缓冲块的指针。

使用hash表结构,用一个散列数组将每一个已经分配的缓冲列表串起来
e.g., 字符缓冲

这里可以对照了解一下hello.c的执行全过程,不再详细叙述。