在C编程中,一般写文件的代码可能会是这样的:
int write_file(const char *filename, unsigned char *data, int data_len)
{
int ret = 0;
FILE *f = NULL;
do {
f = fopen(filename, "wb");
if (NULL == f) {
break;
}
fwrite(data, sizeof(unsigned char), data_len, f);
fflush(f);
ret = 1;
} while (0);
if (NULL != f) {
fclose(f);
}
return ret;
}
如果对可靠性要求不是那么高的场景,这样没有太大问题,但是如果对可靠性要求高,比如我们的场景:程序执行完后可能会被强制关机或断电,那么上述的代码就存在问题,因为可能数据还没有被刷到硬盘,就被强制关机了。那么这时候其实应该这么写:
int write_file(const char *filename, unsigned char *data, int data_len)
{
int ret = 0;
FILE *f = NULL;
do {
f = fopen(filename, "wb");
if (NULL == f) {
break;
}
fwrite(data, sizeof(unsigned char), data_len, f);
fflush(f); //这个API只是把数据从用户态缓冲区刷到内核态缓冲区,实际上并未真正写盘
if (fsync(fileno(f)) != 0) { //加上这个API调用,强制把数据从内核缓冲区刷出到硬盘
break;
}
ret = 1;
} while (0);
if (NULL != f) {
fclose(f);
}
return ret;
}
这是类Unix系统上的做法,这么做的原因及Windows上的做法可以参考下面这个博文:
Windows上似乎以下代码(我没有验证):
if (FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(f))) != TRUE) {
break;
}
功能类似于类Unix的:
if (fsync(fileno(f)) != 0) {
break;
}