遇到机器异常关机时,写log文件信息丢失问题,所以记录下。
Linux实现中在内核设有缓冲区高速缓存或页面高速缓存,大多数磁盘I/O都通过缓冲区进行。当我们向文件写数据时,内核通常先将数据复制到一个缓冲区中,如果该缓冲区尚未写满,则并不将其排入输出队列,而是等待写满或者内核需要重用该缓冲区以便存放其他数据时,才会将该缓冲区排入输出队列,然后等它到达队首时,才进行实际的I/O操作。这就是被称为 延迟写的输出方式。
延迟写减少了磁盘读次数,但是却减低了文件内容跟新的速度。当系统发生故障时,延迟写的方式可能造成文件跟新丢失。为了应对此种情况,linux下提供了sysnc,fsync,fdatasync三个函数来保证实际文件系统与缓冲区中内容的一致。
#include<unistd.h>
int fsync(int fd);
int fdatasync(int fd);
void sync(void);
《1》、sync
该函数只是将所有修改过的块缓冲区排入写队列,然后就返回,他并不等待实际写磁盘操作结束
《2》、fsync
只对由文件描述符fd指定的一个文件起作用,并且等待写磁盘操作结束才返回。
《3》、fdatasync
类似于fsync,但是它只影响文件的数据部分。而除数据外,fsync还会同步更新文件的属性。
《4》C库的fflush
标准的I/O函数(如fread,fwrite)会在内存建立缓冲,该函数刷新内存缓冲,将内容写入内核缓冲,要想将其写入磁盘,还需要调用fsync(先调用fflsuh然后再调用fsync,否则不起作用);
关系:
c库缓冲-----fflush---------〉内核缓冲--------fsync-----〉磁盘
1、例子
int main()
{
FILE* wstream = fopen("test.log","wb+");
int wfd = -1;
if(wstream)
{
char tmp_str[12]="test file sync";
fwrite(tmp, 1, strlen(tmp_str), wstream);
fflush(wstream); //写到缓冲区
wfd = fileno(wstream); //由文件流获取文件描述符
if(wfd != -1)
{
fsync(wfd); //由缓冲区写到磁盘
}
fclose(wstream);
}
else
{
perror("Open test.log: ");
}
return 0;
}
2、参考:
《1》、https://blog.csdn.net/xiaoshengqdlg/article/details/44114939
《2》、unix环境高级编程第三版 – 3.13