【发布时间】:2016-09-14 06:45:18
【问题描述】:
场景:
任务代码(省略错误检查):
// open, write and close
fd = open(name);
write(fd, buf, len);
close(fd);
< more code here **not** issuing read/writes to name but maybe open()ing it >
// open again and fsync
fd = open(name);
fsync(fd);
系统中不再有任务同时访问name。
它是否已定义,更重要的是,它是否会在name 引用的 inode 上同步可能的未完成写入?即,我会在 fsync 之后从文件中读回 buf 吗?
来自 POSIX http://pubs.opengroup.org/onlinepubs/009695399/functions/fsync.html 我会说这似乎是合法的......
谢谢。
5 月 18 日编辑: 感谢您的回答和研究。我(在 2016 年)向 extfs 首席开发人员之一(Ted)提出了这个问题并得到了这个答案:“Posix 不保证,但实际上它应该适用于大多数 文件系统,包括 ext4。 Posix 规范中的关键词是:
fsync() 函数应请求打开文件的所有数据 ^^^^^^^^^^^^^^^^^ 由 fildes 命名的描述符将被传输到存储设备 ^^^^^^^^^^^^^^^^^^^^^^^^^^ 与 fildes 描述的文件相关联。
它没有说“fildes描述的文件的所有数据......”它 说“打开文件描述符的所有数据”。所以技术数据 不保证由另一个文件描述符写入 磁盘。
实际上,文件系统不会尝试从哪个 fd 进来的脏数据 开,所以你不必担心。还有一个写得比什么多的操作系统 严格要求是符合标准的,所以这就是你 一般情况下都会找到,即使它没有保证。”这不如“完全相同的持久保证”那么具体,但相当权威,尽管可能已经过时了。
我试图做的是一个适用于单个文件的“同步”命令。 就像 fsync /some/file 一样,无需同步整个文件系统,例如在 shell 脚本中使用它。 现在(从几年前开始)gnu coreutils 'sync' 可以在单个文件上工作,并且正是这样做的(open/fsync)。提交:https://github.com/coreutils/coreutils/commit/8b2bf5295f353016d4f5e6a2317d55b6a8e7fd00
【问题讨论】:
-
由于你刚刚打开文件描述符,所以没有“filedes命名的打开文件描述符的数据要被传输”,所以我会说没有。
-
@marcolz 这是我的疑问。但我会说
filedes引用的 inode 上的待处理请求是“打开文件描述符的数据” -
This comment 建议你可以写“一堆文件不用fsync就可以全部写出来,然后回去重新打开/fsync”,建议fsync之后关闭工程。这样是有意义的——否则在 close() 之后将无法强制将数据写入磁盘。但是如果能得到一个权威的答案就太好了。我已经开始赏金了。
-
我在
linux-fsdevel上问过这个问题。我got confirmed 至少在撰写本文时,close()/re-open()/fsync()确实不提供与fsync()/close()相同的保证。
标签: c linux unix filesystems posix