Linux/Unix 下實現文件實時同步更新,傳統方案:守護進程 + stat 輪詢。本文提供完整雙文件 init.c(守護進程初始化)與 Realtime_Update.c(輪詢邏輯),並介紹現代高效替代方案 inotify。
標準雙重 fork 分離終端:
void init_daemon() {
int pid;
if (pid = fork()) exit(0); // 父進程退出
else if (pid < 0) exit(1); // 失敗退出
// 子進程 1:成為會話組長,脫離控制終端
setsid();
if (pid = fork()) exit(0); // 子進程 1 退出
else if (pid < 0) exit(1);
// 子進程 2:不再是會話組長,無法重新獲得控制終端
for (int i = 0; i < NOFILE; i++) close(i); // 關閉繼承的文件描述符
chdir("/tmp"); // 改變工作目錄,避免掛載點占用
umask(0); // 重置文件創建掩碼
}
main() {
init_daemon();
struct stat st1, st2;
stat("~/test_file1.txt", &st1);
stat("~/test_file2.txt", &st2);
while (1) {
stat("~/test_file1.txt", &st1);
// 比較修改時間
if (st1.st_mtim.tv_sec > st2.st_mtim.tv_sec ||
(st1.st_mtim.tv_sec == st2.st_mtim.tv_sec && st1.st_mtim.tv_nsec > st2.st_mtim.tv_nsec)) {
system("cp -a ~/test_file1.txt ~/test_file2.txt");
stat("~/test_file2.txt", &st2); // 更新基準
}
sleep(1);
}
}
時間比較函數 timespec_compare 處理秒/納秒精度。
gcc -o Realtime_Update init.c Realtime_Update.c
./Realtime_Update &
inotify 內核級文件系統事件通知,無需輪詢,即時、高效、低資源佔用。
int fd = inotify_init();
int wd = inotify_add_watch(fd, "~/test_file1.txt", IN_MODIFY);
char buf[4096];
while (1) {
int len = read(fd, buf, sizeof(buf));
// 解析 inotify_event,觸發 cp
}
優勢:事件驅動、無延遲、無 CPU 空轉、支援目錄遞歸監控(inotifytools、fsnotify 庫封裝更易用)。
fork + setsid + 關閉描述符 + chdir 是標準範式。stat 輪詢簡單但有延遲(秒級)且佔用 CPU。libuv、Boost.Asio、pyinotify 等)。