fwrite、fflush、fsync和setvbuf调用关系

C库提供了fwrite接口,在调用write之前将数据缓存到buffer,buffer大小可以通过setvbuf来设置。

int setvbuf(FILE *stream, char *buffer, int mode, size_t size)

参数

stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了一个打开的流。

buffer -- 这是分配给用户的缓冲。如果设置为 NULL,该函数会自动分配一个指定大小的缓冲。

mode -- 这指定了文件缓冲的模式:

模式描述

_IOFBF 全缓冲 :对于输出,数据在缓冲填满时被一次性写入。对于输入,缓冲会在请求输入且缓冲为空时被填充。

_IOLBF 行缓冲 :对于输出,数据在遇到换行符或者在缓冲填满时被写入,具体视情况而定。对于输入,缓冲会在请求输入且缓冲为空时被填充,直到遇到下一个换行符。

_IONBF 无缓冲 :不使用缓冲。每个 I/O 操作都被即时写入。buffer 和 size 参数被忽略。

调用关系

当fwrite数据超过buffer大小,就会自动刷新到内核缓存,如果希望立刻刷新,就可以调用fflush。

此时内核缓存的数据并没有立刻同步到磁盘中去,会等待一个IO同步周期,然后同步到磁盘中去,比如在android设备中,同步周期为5秒钟左右,如果开发音视频录制功能,在同步周期到来之前发生掉电或程序Crash,则会发生数据丢失的问题,即使APP已经调用了fwrite。

如果希望内核缓存立刻同步到磁盘,可以调用fsync来强制系统执行IO同步,这个方法是阻塞方法,需要等待IO同步到磁盘完成后才会返回,所以需要注意调用的线程是否可以执行耗时的操作。

关系如下:

app --------fwrite------>  c库缓冲-----fflush--------->内核缓冲--------fsync----->磁盘

最后编辑于
© 著作权归作者所有,转载或内容合作请联系作者