A.3. Fsync

通常 Fsync 是 I/O 密集的運作,但這並不完全正確。
Firefox 會在使用者按下網頁連結,以連上新的頁面時,呼叫 sqlite 函式庫。Sqlite 會呼叫 fsync,同時因為檔案系統的設定(主要是 ext3 與資料的排序模式),在什麼都沒發生時,會產生很長的延遲時間。如果同時間有另一個程序正在複製大檔案時,這延遲時間會多達 30 秒。
然而在其它不使用 fsync 的情形下,轉換到 ext4 檔案系統上問題就會接踵而來。Ext3 的設定是資料順序模式,每幾秒鐘就會清空記憶體,寫入磁碟去。但在 ext4 與 laptop_mode(筆電模式)下,儲存的間隔較長,系統無預期關機時,資料就會流失。雖然現在 ext4 已經更新,但撰寫應用程式時,還是要注意,並適當地使用 fsync
以下這個簡單的範例會讀、寫一個配置檔,顯示了如何備份檔案,以及資料是怎麼流失的:
/* open and read configuration file e.g. ./myconfig */
fd = open("./myconfig", O_RDONLY);
read(fd, myconfig_buf, sizeof(myconfig_buf));
close(fd);
...
fd = open("./myconfig", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
write(fd, myconfig_buf, sizeof(myconfig_buf));
close(fd);
較好的方法是:
/* open and read configuration file e.g. ./myconfig */
fd = open("./myconfig", O_RDONLY);
read(fd, myconfig_buf, sizeof(myconfig_buf));
close(fd);
...
fd = open("./myconfig.suffix", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR
write(fd, myconfig_buf, sizeof(myconfig_buf));
fsync(fd); /* paranoia - optional */
...
close(fd);
rename("./myconfig", "./myconfig~"); /* paranoia - optional */
rename("./myconfig.suffix", "./myconfig");