全缓冲、行缓冲

缓冲(Buffering)的本质

缓冲(Buffering)是计算机中一种常见的数据处理优化技术,核心思想是 用内存临时存储数据,减少直接访问低速设备(如磁盘、网络)的次数,从而提高 I/O 效率。

缓冲模式 宏定义 行为 典型应用场景
全缓冲 _IOFBF 缓冲区满或调用 fflush() 时才进行 I/O 操作 普通磁盘文件
行缓冲 _IOLBF 遇到换行符 \n 或缓冲区满时进行 I/O 操作 终端(stdin/stdout)
无缓冲 _IONBF 每次 I/O 操作都直接调用系统调用(如 read/write stderr(错误输出)

默认缓冲规则

(1) 终端设备(如 /dev/tty
  • stdin(标准输入)、stdout(标准输出):默认是 行缓冲(_IOLBF

    • 例如 printf 输出到终端时,遇到 \n 或缓冲区满才会刷新。

    • 用户输入时,必须按 回车(\n 才会提交数据给程序。

(2) 普通磁盘文件
  • 通过 fopen 打开的文件:默认是 全缓冲(_IOFBF

    • 缓冲区大小通常为 BUFSIZ(如 8192 字节),减少频繁的系统调用。

(3) 管道/套接字
  • 缓冲模式取决于具体实现,可能是行缓冲或全缓冲。

(4) stderr
  • 默认 无缓冲(_IONBF,确保错误信息立即输出。

QA

那用fread读stdin是全缓冲还是行缓冲?

既然是行缓冲是不是意味着,读到换行符fread函数就会结束?

1.默认情况下,stdin 是行缓冲(_IOLBF

  • 终端输入(如键盘)默认是 行缓冲,即:

    • 用户必须按 回车(\n,输入的数据才会提交给 fread

    • 但 fread 不会因为 \n 停止读取,它会继续尝试读满指定字节数(除非遇到 EOF)。

char buf[100];
fread(buf, 1, sizeof(buf), stdin);  // 需按回车后才会读取,但会读满 100 字节(如果有)

2. fread 的行为 vs 缓冲模式

  • fread 是二进制读取函数

    • 它 不关心内容(如 \n),只关心是否读满指定字节数。

    • 即使 stdin 是行缓冲,fread 也会尝试读取尽可能多的数据(直到缓冲区满或 EOF)。

  • 对比 fgets

    • fgets 是文本行读取函数,遇到 \n 会停止。

    • fread 是二进制块读取函数,无视 \n


3. 缓冲模式的本质

  • stdin 的行缓冲:控制的是 数据何时从内核提交给 fread(按回车后提交)。

  • fread 的读取逻辑:决定 如何消费这些数据(读满指定字节数,不因 \n 停止)。

总结

  • 缓冲的核心目标:用内存换速度,减少低速设备的直接访问。

  • C 标准库的缓冲

    • 默认:终端行缓冲(stdin/stdout),文件全缓冲。

    • 可通过 setvbuf 调整。

  • 系统调用无缓冲:如 read()/write() 直接操作内核缓冲区。

你可能感兴趣的:(全缓冲、行缓冲)