IO缓存区

一、标准IO的缓冲区

1.1 数据流动流程图

缓存区结束地址减去缓存区起始地址等于缓存区的内存大小

bash 复制代码
stderr->_IO_buf_end - stderr->_IO_buf_base;

1.2 标准 I/O 缓冲区策略

定义:标准 I/O 中的缓冲区是C语言标准库为优化文件读写效率设计的内存机制

本质上就是一段由FILE结构体管理的内存空间

作用:通过临时存储数据、批量处理,可以减少硬件IO (如磁盘、终端)的交互次数,提升程序效率;

缓冲类型 默认应用场景 缓冲区大小(Linux) 特点
行缓冲 终端设备 (如 stdoutstdin 1024 字节(1KB 遇到换行符或缓冲区满 时刷新,适合交互式设备
全缓冲 普通文件 (如 .txt 4096 字节(4KB 缓冲区满或手动刷新时 才写入,适合文件读写
无缓冲 标准错误stderr 0 字节 数据不暂存,直接写入硬件设备 ,适合立即输出错误信息

占位符是%ld

只有在使用缓存区的才会分配大小不使用的时候大小为0

行缓存只有交互的时候才会分配空间 ,全缓存只有读写操作的时候才会分配空间

二、缓冲区刷新时机

2.1 行缓冲刷新时机

刷新时机 说明
遇到换行符 \n 输出换行时自动刷新缓冲区
程序正常结束 main 函数返回或调用 exit() 时刷新
文件关闭 调用 fclose() 关闭文件时刷新
输入/输出切换 输出状态切换到输入状态 时(如 scanf 前)自动刷新
缓冲区写满 缓冲区已满但未遇到换行符时强制刷新
主动调用 fflush() 手动调用 fflush(fp) 强制刷新指定缓冲区

注:

循环本身并不产生数据 。如果在刷新条件触发之前程序陷入了死循环,那么之前输出的内容会一直卡在缓冲区里,永远不会显示

只有在循环体内反复调用 printf 等输出函数,才会向缓冲区填充数据。

缓冲区溢出并不会"自动刷新",而是会导致程序崩溃。

当**程序不断向缓冲区写入字符,直到写满1024字节,这时无论是否遇到换行符,缓冲区都会自动刷新。**这是那六个条件中的"缓冲区写满"。

2.2 fflush函数

项目 内容
所需头文件 #include <stdio.h>
函数原型 int fflush(FILE *stream);
功能 指定流(stream)缓冲区中尚未写入的内容强制写入到对应的输出设备(如文件、终端等)
参数 stream ------ 用于指定需要刷新缓冲区的流
成功返回值 **0(**刷新了流缓冲区)
失败返回值 EOF,并将 errno 设置为具体的错误类型

2.3 全缓冲刷新时机

刷新时机 说明
程序正常结束 main 函数返回或调用 exit() 时刷新缓冲区
文件关闭 调用 fclose() 关闭文件时刷新缓冲区
输入/输出切换 从输出状态切换到输入状态时自动刷新缓冲区
缓冲区写满 **缓冲区已满(未遇到换行符)**时强制刷新
主动调用 fflush() 手动调用 fflush(fp) 强制刷新指定缓冲区

与行缓冲刷新时机区别是遇到/n不会刷新缓存区

三、手动设置缓冲区

3.1 手动设置缓冲

分类 说明
覆盖默认缓冲策略 不同系统/语言对 IO 流的默认缓冲设置不同(如 C 语言中 stdout 默认行缓冲,stderr 默认无缓冲),手动设置可按需调整
性能与实时性平衡 行缓冲 :适合交互式输出(如命令行程序),每行输出后自动刷新 • 全缓冲 :适合大量数据批量写入(如日志文件),减少 IO 次数 • 无缓冲:适合需要立即显示的关键信息(如错误日志)
特殊场景需求 例如网络编程中避免数据堆积,或调试时强制输出中间结果
日志系统 根据日志级别设置缓冲:错误日志无缓冲,普通日志全缓冲
交互式工具 命令行程序中确保用户输入后立即响应
嵌入式系统 受限内存环境下自定义缓冲区大小

3.2 setbuf函数

项目 内容
所需头文件 #include <stdio.h>
函数原型 void setbuf(FILE *stream, char *buf);
功能 设置指定文件流的缓冲区
参数 - stream 指向 FILE 对象的指针,标识要设置缓冲区的文件流
参数 - buf 指向用户提供的缓冲区的指针 • 如果提供了缓冲区,其大小必须至少为 BUFSIZ 字节(通常在 stdio.h 中定义) • 如果为 NULL,则是无缓冲模式
返回值
分类 说明
全缓冲模式 如果 buf 指向一个大小大于 0 的缓冲区,那么 IO 操作将使用全缓冲模式
无缓冲模式 如果 bufNULL,或者是大小为 0,那么 IO 操作将变为无缓冲模式
调用时机 应该在打开文件流之后、任何 IO 操作之前调用,否则可能不会生效
缓冲区大小 使用自定义缓冲区时,确保缓冲区足够大,以避免缓冲区溢出
生命周期管理 使用自定义缓冲区时,不要在 buf 指向的缓冲区被释放后再进行 IO 操作,以免导致未定义的行为

3.3 sleep函数

项目 内容
所需头文件 #include <unistd.h>
函数原型 unsigned int sleep(unsigned int seconds);
功能 用于让程序暂停执行指定的时间
参数 - seconds 指定程序暂停执行的秒数
成功返回值 0(表示休眠了完整的指定秒数)
失败返回值 若程序被信号中断,返回未休眠的秒数(即剩余未休眠完的秒数)

3.4 setvbuf函数

项目 内容
所需头文件 #include <stdio.h>
函数原型 int setvbuf(FILE *stream, char *buf, int mode, size_t size);
功能 更加灵活地控制文件流的缓冲行为,允许指定缓冲模式和缓冲区的大小。 注意 :该函数必须在对 stream 执行任何其他操作前调用
参数 - stream 指向 FILE 对象的指针,标识要设置缓冲区的文件流
参数 - buf 指向用户提供的缓冲区的指针 • 如果为 NULL,函数会自动分配一个大小为 size 的缓冲区
参数 - mode 缓冲模式,必须是以下之一: • _IOFBF:全缓冲 • _IOLBF:行缓冲 • _IONBF:无缓冲(当 mode 为 _IONBF 时,size 参数被忽略)
参数 - size 缓冲区的大小(以字节为单位)
成功返回值 0
失败返回值 0

注意事项

分类 注意事项
调用时机 setvbuf 必须在文件流执行任何读写操作之前调用(文件流初始化后),否则可能导致设置失效或触发未定义行为
自定义缓冲区大小(buf != NULL 需确保缓冲区大小 size 与实际需求匹配: • size 过小:可能导致数据溢出 • size 过大:会浪费内存资源
自动分配缓冲区(buf = NULL size 需设置合理值(通常建议不小于系统默认缓冲区大小,如 BUFSIZ),避免因缓冲区过小影响性能或触发溢出
缓冲区生命周期 禁止在缓冲区被释放后对文件流执行 IO 操作,否则会触发未定义行为(如访问已释放内存导致崩溃)
无缓冲模式(_IONBF mode_IONBF(无缓冲)时,size 参数会被忽略(即使设置非零值也无效),需避免依赖 size 配置无缓冲模式
平台兼容性 不同系统对 mode 的支持可能有差异(如某些嵌入式环境可能不支持行缓冲 _IOLBF),需根据实际平台验证行为
相关推荐
志栋智能2 小时前
超自动化巡检:洞察未知隐患,助您事前不出事
大数据·运维·网络·数据库·自动化
出海干货炒鱿鱼2 小时前
IP大科普:住宅IP、机房IP、原生IP、双ISP
运维·服务器
somi72 小时前
ARM-驱动-03 Linux 字符设备驱动开发
linux·arm开发·驱动开发·自用
CDN3602 小时前
高防服务器带宽跑满、业务掉线?流量限制与清洗优化
运维·服务器
似水এ᭄往昔2 小时前
【Linux】--程序地址空间
linux·运维·服务器
云飞云共享云桌面2 小时前
8-10位研发3D(sw、ug、creo)画图如何共享一台工作站?
运维·服务器·网络·数据库·3d·电脑
Turboex邮件分享2 小时前
邮件系统中的抗拒绝服务(DDoS)攻击防护
运维·网络·安全·ddos·软件需求
成为你的宁宁2 小时前
【docker镜像加速器配置】
运维·docker·容器
DeeplyMind2 小时前
Linux 内核补丁提交(Upstream)完整指南
linux·upstream