【问题标题】:How to prevent data loss when closing a file descriptor?关闭文件描述符时如何防止数据丢失?
【发布时间】:2016-11-21 16:44:58
【问题描述】:

当我发出write() 时,我的数据会进入一些内核空间缓冲区。对物理层的实际提交(“phy-commit”)(可能)被推迟,直到..(到底是什么事件?)

当我为文件描述符发出close() 时,然后

如果 [...],则释放与打开文件描述相关的资源

这是否意味着释放(释放)那些包含我的数据的内核缓冲区?这些缓冲区中包含的宝贵数据会怎样?会丢失吗?

如何防止这种损失?

通过fsync()?它请求一个明确的 phy-commit。我想要么立即(同步调用),要么仅“短时间”推迟并排队等待后续操作,至少是破坏性操作。

但我不太想要立即或紧急的 phy-commit。只是(保留我的数据并且)不要忘记稍后再做 phy-commit。


来自man fclose

fclose() 函数 [...] 关闭底层文件描述符。
...
fclose() 仅刷新 C 库提供的用户空间缓冲区。为确保数据物理存储在磁盘上,内核缓冲区也必须刷新,例如使用 sync(2) 或 fsync(2)。

这可能表明fsync 不必先于 close(或fclose,其中包含close),但可以(甚至必须)在它之后。所以close() 不会有很大的破坏性...

【问题讨论】:

  • close 和 fclose 足以让数据到达磁盘,除非在接下来的几毫秒内出现物理断开或断电等情况。
  • 内核在实际提交数据之前不会释放其缓冲区。你不需要做任何事情。

标签: c linux data-loss fsync


【解决方案1】:

这是否意味着释放(释放)那些包含我的数据的内核缓冲区?这些缓冲区中包含的宝贵数据会怎样?会丢失吗?

没有。在将数据写入底层文件之前,内核缓冲区不会被释放。因此,不会有任何数据丢失(除非真的出现问题 - 例如系统断电)。 该数据是否会立即写入物理文件是另一个问题。它可能取决于文件系统(可能正在缓冲)和/或任何硬件缓存。 就您的用户程序而言,成功的close() 调用可视为成功写入文件。

这可能表明 fsync 不必在 close 之前(或 fclose,其中包含一个 close),但可以(甚至必须)在它之后。所以 close() 不会有很大的破坏性...

在调用close() 之后,文件描述符的状态不会被POSIX 指定(不管close() 是否成功)。所以,你不能在调用close()之后使用fsync(fd);。 请参阅:POSIX/UNIX: How to reliably close a file descriptor

不,这并不表明close() 具有破坏性。它表明 C 库可能在用户中进行自己的缓冲,并建议使用 fsync() 将其刷新到内核(现在,我们处于与之前所说的相同的位置)。

【讨论】:

  • 对于答案的最后一段:您可以使用 fileno() 和显式 fflush() 来解决它:序列将是 fd=fileno(FH);冲洗(FH);同步(fd); fclose(FH);
猜你喜欢
  • 2017-06-20
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2017-08-22
  • 1970-01-01
  • 1970-01-01
  • 2017-09-05
  • 2021-03-12
相关资源
最近更新 更多