fsync – 文件同步
函数介绍
fsync
系统调用用于将文件的所有修改强制写入磁盘,确保数据的持久性。它会同步文件的数据和元数据(如修改时间、访问时间等),是保证数据安全的重要函数。掌握fsync系统调用,确保数据安全写入磁盘。了解其功能、用法及示例代码,提升文件操作效率与可靠性。关键词:fsync…
fsync系统调用, 文件同步fsync, Linux fsync使用示例, 如何使用fsync确保数据持久性, fsync函数详解, fsync与数据安全, 理解fsync及其重要性, 使用fsync提高文件操作安全性, fsync在编程中的应用, fsync系统调用实战案例
函数原型
#include <unistd.h>
int fsync(int fd);
功能
将文件描述符对应的文件所有修改(包括数据和元数据)强制写入磁盘。
参数
int fd
: 文件描述符
返回值
- 成功时返回0
- 失败时返回-1,并设置errno:
EBADF
: 文件描述符无效EIO
: I/O错误EINVAL
: 文件描述符不支持同步EROFS
: 文件在只读文件系统上
相似函数
fdatasync()
: 只同步文件数据,不同步所有元数据sync()
: 同步所有文件系统缓冲区msync()
: 同步内存映射文件
示例代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
int main() {
int fd;
struct stat stat_buf;
time_t write_time, sync_time;
printf("=== Fsync函数示例 ===\n");
// 示例1: 基本的文件同步操作
printf("\n示例1: 基本的文件同步操作\n");
// 创建测试文件
fd = open("test_fsync.txt", O_CREAT | O_RDWR | O_TRUNC, 0644);
if (fd == -1) {
perror("创建测试文件失败");
exit(EXIT_FAILURE);
}
printf("成功创建测试文件,文件描述符: %d\n", fd);
// 写入数据
const char *data1 = "First line of data\n";
if (write(fd, data1, strlen(data1)) == -1) {
perror("写入第一行数据失败");
close(fd);
exit(EXIT_FAILURE);
}
printf("写入第一行数据: %s", data1);
// 获取写入时间
time(&write_time);
printf("写入时间: %s", ctime(&write_time));
// 同步文件到磁盘
printf("开始同步文件到磁盘...\n");
time(&sync_time);
if (fsync(fd) == -1) {
perror("文件同步失败");
} else {
printf("文件同步成功\n");
printf("同步完成时间: %s", ctime(&sync_time));
}
// 再写入更多数据
const char *data2 = "Second line of data\nThird line of data\n";
if (write(fd, data2, strlen(data2)) == -1) {
perror("写入更多数据失败");
} else {
printf("写入更多数据成功\n");
}
// 再次同步
if (fsync(fd) == -1) {
perror("第二次文件同步失败");
} else {
printf("第二次文件同步成功\n");
}
// 示例2: 同步前后文件状态对比
printf("\n示例2: 同步前后文件状态对比\n");
// 获取同步前的文件状态
if (fstat(fd, &stat_buf) == -1) {
perror("获取文件状态失败");
} else {
printf("同步前文件状态:\n");
printf(" 文件大小: %ld 字节\n", stat_buf.st_size);
printf(" 最后修改时间: %s", ctime(&stat_buf.st_mtime));
printf(" 最后访问时间: %s", ctime(&stat_buf.st_atime));
}
// 写入数据但不同步
const char *unsynced_data = "Unsynced data\n";
if (write(fd, unsynced_data, strlen(unsynced_data)) == -1) {
perror("写入未同步数据失败");
}
// 再次获取文件状态(可能还未写入磁盘)
if (fstat(fd, &stat_buf) == -1) {
perror("再次获取文件状态失败");
} else {
printf("写入未同步数据后的文件状态:\n");
printf(" 文件大小: %ld 字节\n", stat_buf.st_size);
}
// 同步文件
if (fsync(fd) == -1) {
perror("同步文件失败");
} else {
printf("文件同步完成\n");
}
// 同步后再次获取文件状态
if (fstat(fd, &stat_buf) == -1) {
perror("同步后获取文件状态失败");
} else {
printf("同步后文件状态:\n");
printf(" 文件大小: %ld 字节\n", stat_buf.st_size);
printf(" 最后修改时间: %s", ctime(&stat_buf.st_mtime));
}
// 示例3: 性能对比演示
printf("\n示例3: 性能对比演示\n");
// 测试不使用fsync的写入性能
clock_t start_time = clock();
for (int i = 0; i < 1000; i++) {
char buffer[50];
sprintf(buffer, "Line %d: Performance test data\n", i);
if (write(fd, buffer, strlen(buffer)) == -1) {
perror("性能测试写入失败");
break;
}
}
clock_t without_sync_time = clock() - start_time;
printf("不使用fsync写入1000行数据耗时: %f 秒\n",
((double)without_sync_time) / CLOCKS_PER_SEC);
// 测试使用fsync的写入性能
start_time = clock();
for (int i = 1000; i < 2000; i++) {
char buffer[50];
sprintf(buffer, "Line %d: Performance test data with sync\n", i);
if (write(fd, buffer, strlen(buffer)) == -1) {
perror("性能测试写入失败");
break;
}
if (fsync(fd) == -1) {
perror("同步失败");
break;
}
}
clock_t with_sync_time = clock() - start_time;
printf("使用fsync写入1000行数据耗时: %f 秒\n",
((double)with_sync_time) / CLOCKS_PER_SEC);
printf("注意: fsync会显著降低写入性能,但保证数据安全\n");
// 示例4: 错误处理演示
printf("\n示例4: 错误处理演示\n");
// 尝试对无效文件描述符同步
if (fsync(999) == -1) {
printf("对无效文件描述符同步: %s\n", strerror(errno));
}
// 尝试对只读文件同步(应该成功)
int readonly_fd = open("test_fsync.txt", O_RDONLY);
if (readonly_fd != -1) {
if (fsync(readonly_fd) == -1) {
printf("对只读文件同步: %s\n", strerror(errno));
} else {
printf("对只读文件同步成功\n");
}
close(readonly_fd);
}
// 示例5: 数据安全重要性演示
printf("\n示例5: 数据安全重要性演示\n");
// 创建重要的数据文件
int important_fd = open("important_data.txt", O_CREAT | O_RDWR | O_TRUNC, 0644);
if (important_fd != -1) {
printf("创建重要数据文件\n");
// 写入重要数据
const char *important_data = "Very important data that must not be lost\n";
if (write(important_fd, important_data, strlen(important_data)) != -1) {
printf("写入重要数据\n");
// 对于重要数据,必须同步到磁盘
if (fsync(important_fd) == -1) {
perror("重要数据同步失败");
} else {
printf("重要数据已安全同步到磁盘\n");
}
}
close(important_fd);
unlink("important_data.txt");
}
// 清理资源
printf("\n清理资源...\n");
if (close(fd) == -1) {
perror("关闭文件失败");
} else {
printf("成功关闭文件描述符 %d\n", fd);
}
if (unlink("test_fsync.txt") == -1) {
perror("删除测试文件失败");
} else {
printf("成功删除测试文件\n");
}
return 0;
}