首页 文章

关闭后调用fsync(2)(2)

提问于
浏览
2

场景:

任务代码(省略错误检查):

// 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我会说它似乎合法......

谢谢 .

编辑可能18:感谢您的答案和研究 . 我把这个问题(2016年)带到了一个extfs主要开发人员(Ted)并得到了这个答案:“Posix不保证,但实际上它应该适用于大多数文件系统,包括ext4 . Posix中的关键措辞规格是:

fsync()函数应该请求将由fildes命名的打开文件^^^^^^^^^^^^^^^^^描述符的所有数据传送到存储设备^^^^^^^与fildes描述的文件相关联的^^^^^^^^^^^^^^^^^^^ .

它没有说“fildes描述的文件的所有数据......”它说“打开文件描述符的所有数据” . 因此,技术上不能保证将另一个文件描述符写入的数据同步到磁盘 .

实际上,文件系统不会尝试使用fd的脏数据,因此您无需担心 . 并且写入比严格要求更多的操作系统是符合标准的,所以这就是你将会发现的一般情况,即使它没有保证 . “这不像”完全相同的durabily guarrantees“那么具体,但是非常权威,即使可能已经过时了 .

我试图做的是一个'sync'命令,它可以处理单个文件 . 像fsync / some / file一样,无需同步整个文件系统,例如在shell脚本中使用它 . 现在(从几年前开始)gnu coreutils 'sync'适用于单个文件并且正是这样(open / fsync) . 提交:https://github.com/coreutils/coreutils/commit/8b2bf5295f353016d4f5e6a2317d55b6a8e7fd00

2 回答

  • 1

    Noclose() re- open() fsync() 未提供与 fsync() close() 相同的保证 .

    来源:我took this questionlinux-fsdevel 邮件列表和got the answer

    close()/ re-open()/ fsync()序列是否提供与fsync()/ close()相同的持久性保证?简短的回答是否定的,后者提供了更好的保证 . 更长的答案是持久性保证取决于内核版本,因为情况在v4.13,v4.14中已经发生变化,现在再次发生在v4.17-rc和稳定内核中 .

    进一步的相关链接是:

    特别是,后面的链接描述了如何

    关闭FD后

    • ,你将失去所有强制执行的方法
      fsync() 失败后

    • ,您无法再次调用 fsync() ,希望现在您的数据会被写入

    • must re-do/confirm all writing work如果发生这种情况

  • 2

    POSIX fsync()的当前(2017)规范识别基本功能和可选功能:

    fsync()函数应请求将fildes命名的打开文件描述符的所有数据传输到与fildes描述的文件关联的存储设备 . 转移的性质是实施定义的 . 在系统完成该操作或检测到错误之前,fsync()函数不会返回 . [SIO]⌦如果定义了_POSIX_SYNCHRONIZED_IO,则fsync()函数将强制所有与文件描述符fildes指示的文件关联的当前排队I / O操作进入同步I / O完成状态 . 所有I / O操作都应按照同步I / O文件完整性完成的定义完成 . ⌫

    如果实现未定义 _POSIX_SYNCHRONIZED_IO ,则重新打开的文件描述符没有未写入的数据要传输到存储设备,因此 fsync() 调用实际上是无操作 .

    如果 _POSIX_SYNCHRONIZED_IO 由实现定义,则重新打开的文件描述符将确保写入与文件关联的任何文件描述符的所有数据都被传输到存储设备 .

    Conformance上的标准部分包含有关选项和选项组的信息 . Definitions部分有定义382..387,它定义了同步I / O和同步I / O的各个方面(是的,它们是不同的 - 也要注意打开文件描述符和打开文件描述) . 有关同步I / O的含义,请参阅“定义”部分的Realtime部分 .

    它定义了:

    3.382同步输入和输出增强的确定性和鲁棒性改进机制数据输入和输出机制,以便应用程序可以确保被操纵的数据实际存在于辅助大容量存储设备上 . 3.383同步I / O完成已成功传输或诊断为不成功的I / O操作的状态 . 3.384同步I / O数据完整性完成对于读取,操作完成或诊断如果不成功 . 仅当数据图像已成功传输到请求进程时,才完成读取 . 如果在请求同步读取操作时有任何影响要读取的数据的挂起写入请求,则在读取数据之前成功传输这些写入请求 . 用于写入,当操作完成或诊断为不成功时 . 只有在成功传输写请求中指定的数据并成功传输检索数据所需的所有文件系统信息时,写操作才会完成 . 在返回到调用进程之前,不需要成功传输数据检索不需要的文件属性(访问时间,修改时间,状态更改时间) . 3.385同步I / O文件完整性完成与同步I / O数据完整性完成相同,并且在返回之前成功传输了与I / O操作相关的所有文件属性(包括访问时间,修改时间,状态更改时间)到调用过程 . 3.386同步I / O操作对文件执行的I / O操作,该应用程序保证其数据和文件的完整性 . 3.387同步I / O操作一种I / O操作,在I / O操作完成之前,阻止请求I / O的线程继续使用处理器 . 注意:同步I / O操作不表示同步I / O数据完整性完成或同步I / O文件完整性完成 .

    不清楚“与文件描述符指示的文件关联的所有当前排队的I / O操作”是否适用于进程 . 从概念上讲,我认为应该这样,但措辞不是黑白两色(或淡黄色黑色) . 它当然应该适用于当前进程中引用同一文件的任何打开文件描述符 . 目前尚不清楚它是否适用于当前进程中先前打开(和关闭)的文件描述符 . 如果它适用于所有进程,则它应包括当前进程的排队I / O.如果它不适用于所有进程,则可能不适用于所有进程 .

    鉴于此和 fsync() 的基本原理说明,假设 fsync() 操作对与关闭文件描述符关联的排队操作没有影响,这是最安全的 . 如果希望 fsync() 生效,请在关闭文件描述符之前调用它 .

相关问题