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");