C语言写入文件后立即重启失效的问题及优化需求
解决C程序写入文件后立即重启丢失数据的问题
这个问题的核心在于文件系统的缓存机制:当你调用fclose()时,C标准库会把用户态的缓存刷到内核的页缓存,但内核为了性能优化,不会立刻把页缓存写入物理磁盘——而重启会直接中断这个异步刷盘过程,导致数据丢失。sleep(10)能解决只是因为给了内核足够的时间完成异步刷盘,但这显然不是可靠且规范的做法。
你已经试过fflush(fp),但它只负责把用户空间的缓冲区数据推送到内核,并没有强制内核把数据写入物理磁盘。下面是两种更严谨的解决方法:
方法1:使用fsync()强制刷盘
修改你的writeToConfFile函数,在fclose()前先调用fsync(),确保内核将文件数据同步到磁盘:
#include <unistd.h> // 引入fsync所需头文件 int writeToConfFile(char* filename, char* newConf) { FILE *fp; int status; int fd; fp = fopen(filename, "w"); if (fp == NULL) { // 务必添加文件打开失败的错误判断 return -1; } fprintf(fp,"%s", newConf); // &newConf[0]可直接简化为newConf,效果完全一致 fflush(fp); // 先将用户态缓存刷入内核 fd = fileno(fp); // 获取文件对应的文件描述符 if (fd != -1) { fsync(fd); // 强制内核把该文件的所有数据写入物理磁盘 } status = fclose(fp); return status; }
方法2:使用O_SYNC标志打开文件
如果不想额外调用fsync,可以在打开文件时直接使用O_SYNC标志,让所有写入操作都直接同步到磁盘(这种方式会牺牲一点性能,但对于你只写一次就重启的场景完全适用):
#include <fcntl.h> // 引入O_SYNC所需头文件 #include <stdio.h> #include <unistd.h> #include <string.h> int writeToConfFile(char* filename, char* newConf) { int fd; ssize_t bytes_written; // 用O_SYNC标志打开文件,写入直接同步到磁盘 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644); if (fd == -1) { return -1; } bytes_written = write(fd, newConf, strlen(newConf)); close(fd); // 返回写入是否成功的状态 return (bytes_written == strlen(newConf)) ? 0 : -1; }
额外注意事项
- 错误处理:你的原代码缺少
fopen失败的判断逻辑,实际项目中一定要补上,避免空指针操作引发崩溃。 - 性能优化:如果不需要同步文件元数据(比如修改时间),可以用
fdatasync()替代fsync(),它只会同步文件内容,性能会稍好一些。 - 兼容性:上面两种方法都是POSIX标准接口,在旧版Debian系统上完全兼容,能保证数据真正写入磁盘后再执行重启操作。
内容的提问来源于stack exchange,提问作者Kepedizer
相关产品推荐
相关产品推荐

