有些刚接触C语言的同学可能会遇到以下这种情况:“printf()一直打印不出东西出来,直到某一刻却输出来一大堆东西,然后回头加上'\n'之后又可以正常输出了。”这是为什么呢?这就是标准IO的缓冲区在作怪,printf()是行缓冲的,也就是说只有遇到'\n'才会马上把内容刷出来,否则只能等到程序退出或者标准IO缓冲区满了才会把内容刷出来。
标准IO缓冲区
如下图所示,每当使用标准IO的写操作函数,试图将数据写入文件 a.txt 时,数据都会流过缓冲区(一般大小为1024字节),然后再在适当的时刻冲洗(或称刷新,flush)到内核,最后才真正写入设备文件。
按照缓冲区按照什么时候冲洗数据到内核,可以将缓冲区分成以下三类:
- 不缓冲类型:
- 一旦有数据,立刻将数据冲洗到文件(立即在存储器中更新文件)
- 全缓冲类型:
- 一旦填满缓冲区,立刻将数据冲洗到文件
- 程序正常退出时,立刻将数据冲洗到文件
- 遇到 fflush() 强制冲洗时,立刻将数据冲洗到文件
- 关闭文件时,立刻将数据冲洗到文件
- 读取文件内容时,立刻将数据冲洗到文件
- 改变缓冲区类型时,立刻将数据冲洗到文件
- 行缓冲类型:
- 同全缓冲类型
- 一旦遇到’\n’时,立刻将数据冲洗到文件
关键点:
- 缓冲(buffer)都是针对写操作而言的,缓冲的存在是为了提高写效率(数据量比较大的情况下)。
- 对于标准输出而言,默认是行缓冲的;
- 对于标准出错而言,默认是不缓冲的;
- 对于普通文件而言,默认都是全缓冲类型。
- 滞留在缓冲区中的数据有时被称为脏数据(dirty data),脏数据的存在代表程序操作的结果与文件真实状态不一致,若未正常冲洗这些脏数据就退出程序则有可能会造成数据丢失。
- 这三种缓冲类型,可以通过函数 setbuf()/setvbuf() 来修改。
setbuf():
setvbuf():
经过好几节的分享,终于把系统IO和标准IO的知识点给大家整理了一遍。
前面几节的内容:
要对文件操作,用系统IO还是标准IO?不清楚的小白请进来学习
系统IO常用的API接口,你认识多少个?会用多少个?新手一定要看
度白嵌入式,持续分享通俗易懂的嵌入式知识。欢迎志同道合的朋友关注交流~