文件流缓冲区
每个进程都各自维护一个文件流表,和文件描述符表类似,并且这些文件流都有自己对应的缓冲区
缓冲区的设计就是为了减少磁盘io,加快io的速度
缓冲区模式
通过setvbuf或者setbuf两个函数设置缓冲区的模式
无缓冲区
就是禁用缓冲区的意思,这种模式下,就相当于直接调用write函数,不过在调用write之前可能还要处理一些格式化输出等问题,这是和直接调用write的一个小区别
行缓冲区
当标准输出(或者输入)定向到终端时,默认采用行缓冲模式,就是接收到换行符就刷新缓冲区
块缓冲区
当缓冲区的数据达到一个块的大小时,刷新缓冲区,重定向时,默认使用块缓冲区
全缓冲区
当数据填满缓冲区时,刷新缓冲区
总结对比
特性 | 无缓冲区(No Buffering) | 行缓冲区(Line Buffering) | 块缓冲区(Block Buffering) | 全缓冲区(Full Buffering) |
---|---|---|---|---|
定义 | 数据不经过缓冲,直接写入目标设备 | 每当输入一行数据时,才进行输出 | 数据以块为单位进行缓冲,达到块大小后输出 | 数据在缓冲区中,直到填满后一次性输出 |
刷新时机 | 每次写入操作都立即刷新 | 每当遇到换行符时刷新 | 当缓冲区满或达到特定块大小时刷新 | 缓冲区满或显式调用刷新时才输出 |
内存使用 | 无额外内存开销 | 较少的内存开销 | 预定的块大小内存开销 | 较大的内存开销,通常是输出的总大小 |
性能 | 频繁I/O操作,性能较低 | 适合逐行处理,性能适中 | 减少I/O操作,提高性能 | 适合长时间不需要输出的场景,性能较高 |
适用场景 | 实时处理要求高的场景 | 交互式程序或逐行输出 | 大数据处理或文件写入 | 批处理或需要大量输出的场景 |
实时反馈 | 反馈及时 | 逐行反馈 | 反馈延迟,直到块大小达到 | 反馈延迟,直到缓冲区满 |
与fork和exit之间的交互
fork函数用于创建子进程,这样的话子进程会复制一份父进程的stdio流缓冲区
exit函数在调用_exit函数前,会刷新所有stdio流缓冲区
这两个配合起来,有时候就会发现有的输出打印了两份,这是因为缓冲区没有及时刷新的原因,有以下几种办法
- 可以设置缓冲区模式
- 使用fflush立即刷新
- 父进程使用exit函数在程序结束后刷新,子进程使用_exit函数退出,该函数不刷新缓冲区
所以在有多进程的情况下使用stdio流,要注意缓冲区的模式,以及何时刷新缓冲区,避免出现意外情况
标签:输出,函数,stdio,exit,刷新,缓冲区 From: https://www.cnblogs.com/dylaris/p/18445038