以下几个系统调用用来将buffer中的数据写回到磁盘中。
其中:
系统调用sync先将数据写到buffer,再从buffer写回磁盘中;
它是异步调用,函数返回但I/O操作可能未完成。
fsync系统调用会将metadata和数据区数据都写回到磁盘中;
它是同步调用,函数返回时I/O操作即完成。
fdatasync只是将数据区数据写回磁盘中,metadata不会写回磁盘。
#include <unistd.h>
int fsync(int fd);
int fdatasync(int fd);
void sync(void);
所以,可以根据具体需要决定是调用fsync还是sync抑或是fdatasync系统调用。
metadata:data about data,即文件的描述性信息比如文件大小、
最后修改时间、最后访问时间、文件权限等等。
fsync与fflush的区别?
#include <stdio.h>
int fflush(FILE *stream);
fflush是libc提供的库函数,而fsync是操作系统提供的系统调用;
fflush是从c库缓冲区写到内核缓冲区,而fsync是从内核缓冲区写到磁盘中;
fsync才会真正的写磁盘。
为什么还需要将数据写回到磁盘?
linux系统下,大多数磁盘I/O都通过缓存进行。
当写数据回磁盘时,并不是立即将数据写回到磁盘,
而是将数据从内核拷贝到buffer中并且在必要时将数据真正回写到磁盘中。
这就是delay write。
这种必要时是指:
1. buffer已满;
2. 到了周期性写磁盘的时间。
buffer数据结构:
struct buffer_head{
…
bool b_dirty;
time time;
};
其中成员b_dirty用来表明缓冲区是否被修改;
成员time表示这个dirty buffer需要在time这个时间后会自动回写,
这是由linux内核线程kflush完成的?
延迟写减少了读写磁盘的次数,提高了写文件的效率。
但带来的一个问题就是:
写文件时并不能立即更新到磁盘中;
如果此时系统断电或遇到其它不可预知的故障,这样就会造成文件更新内容的丢失。
所以linux系统提供了fsync/sync等系统调用共用户在需要时将数据立即写回磁盘中。