1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
| #define _GNU_SOURCE // 启用 GNU 扩展,可能需要用于 syncfs #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> // 包含 open, O_* flags #include <sys/stat.h> // 包含 open modes #include <string.h> #include <errno.h> #include <time.h> // 包含 clock_gettime #include <sys/syscall.h> // 包含 SYS_syncfs #include <linux/fs.h> // 包含 SYNCFS 等定义 (如果需要)
// 计算时间差(毫秒) double time_diff_ms(struct timespec start, struct timespec end) { return ((end.tv_sec - start.tv_sec) * 1000.0) + ((end.tv_nsec - start.tv_nsec) / 1000000.0); }
// 封装 syncfs 调用,处理不同 glibc 版本的兼容性 int my_syncfs(int fd) { // 尝试直接调用 syncfs (如果 glibc 支持) // 如果编译报错,注释掉 #ifdef 部分,只保留 syscall 部分 #ifdef SYS_syncfs // 检查是否定义了系统调用号 return syscall(SYS_syncfs, fd); #else // 如果你的 glibc 版本较新,可能直接支持 syncfs 函数 // return syncfs(fd); fprintf(stderr, "syncfs system call not available on this system.\n"); return -1; #endif }
int main() { const char *file1_name = "/tmp/sync_test_file1.txt"; // /tmp 通常在根文件系统或 tmpfs const char *file2_name = "/home/user/sync_test_file2.txt"; // 假设 /home 是另一个分区 int fd1, fd2; struct timespec start, end; double elapsed_time;
printf("--- Demonstrating sync and syncfs ---\n"); printf("PID: %d\n", getpid());
// 1. 创建并写入两个测试文件 printf("\n1. Creating and writing test files...\n");
// --- 文件 1 --- fd1 = open(file1_name, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd1 == -1) { perror("open file1"); // 如果 /home/user 不可写,跳过 file2 printf("Skipping file2 due to open error.\n"); fd2 = -1; } else { printf("Opened %s\n", file1_name); if (write(fd1, "Data for file 1 on root/tmp filesystem.\n", 40) != 40) { perror("write file1"); } // 注意:不要 close,保持 fd1 打开用于 syncfs }
// --- 文件 2 (可能在不同文件系统) --- fd2 = open(file2_name, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd2 == -1) { perror("open file2"); printf("Skipping operations on file2.\n"); } else { printf("Opened %s\n", file2_name); if (write(fd2, "Data for file 2 on home filesystem.\n", 37) != 37) { perror("write file2"); } // 注意:不要 close,保持 fd2 打开用于 syncfs }
printf("\nData written to files. It's likely in the page cache now.\n");
// 2. 演示 syncfs: 同步特定文件系统 printf("\n2. --- Demonstrating syncfs ---\n"); if (fd1 != -1) { printf("Calling syncfs() on the filesystem containing %s...\n", file1_name); clock_gettime(CLOCK_MONOTONIC, &start); if (my_syncfs(fd1) == -1) { perror("syncfs fd1"); printf("This might be because syncfs is not supported or fd is invalid.\n"); } else { clock_gettime(CLOCK_MONOTONIC, &end); elapsed_time = time_diff_ms(start, end); printf("syncfs(fd1) completed in %.2f ms.\n", elapsed_time); printf("This synced only the filesystem containing %s.\n", file1_name); } }
if (fd2 != -1) { printf("Calling syncfs() on the filesystem containing %s...\n", file2_name); clock_gettime(CLOCK_MONOTONIC, &start); if (my_syncfs(fd2) == -1) { perror("syncfs fd2"); } else { clock_gettime(CLOCK_MONOTONIC, &end); elapsed_time = time_diff_ms(start, end); printf("syncfs(fd2) completed in %.2f ms.\n", elapsed_time); printf("This synced only the filesystem containing %s.\n", file2_name); } }
// 3. 演示 sync: 同步所有文件系统 printf("\n3. --- Demonstrating sync ---\n"); printf("Calling sync() to flush ALL filesystems...\n"); clock_gettime(CLOCK_MONOTONIC, &start); sync(); // sync() 没有返回值 clock_gettime(CLOCK_MONOTONIC, &end); elapsed_time = time_diff_ms(start, end); printf("sync() completed in %.2f ms.\n", elapsed_time); printf("This synced data for ALL mounted filesystems on the system.\n");
// 4. 关闭文件描述符 if (fd1 != -1) close(fd1); if (fd2 != -1) close(fd2);
// 5. 清理测试文件 (可选) printf("\n4. --- Cleaning up ---\n"); if (fd1 != -1) { if (unlink(file1_name) == 0) { printf("Deleted %s\n", file1_name); } else { perror("unlink file1"); } } if (fd2 != -1) { if (unlink(file2_name) == 0) { printf("Deleted %s\n", file2_name); } else { perror("unlink file2"); } }
printf("\n--- Summary ---\n"); printf("1. sync(): Flushes dirty data for ALL mounted filesystems. No return value.\n"); printf("2. syncfs(fd): Flushes dirty data for ONLY the filesystem containing the file referred to by 'fd'. Returns 0 on success.\n"); printf("3. syncfs is more targeted and usually faster than sync.\n"); printf("4. Use sync() before system shutdown. Use syncfs() or fsync() for specific data safety in applications.\n");
return 0; }
|