ftruncate() 是异步的吗?

Posted

技术标签:

【中文标题】ftruncate() 是异步的吗?【英文标题】:Is ftruncate() asynchronous? 【发布时间】:2012-02-27 14:23:38 【问题描述】:

我正在尝试用 C++ 编写一个类,它提供了一种以原子方式附加到文件的方法,即使在写入过程中出现电源故障的情况下也是如此。

首先,我将我当前的文件位置(距文件开头的 64 偏移量,以字节为单位)写入一个单独的日志文件。然后,我将请求的数据写入日期文件的末尾。最后,我在日志文件上调用 ftruncate()(将截断大小设置为 0)。

主要思想是,如果曾经要求此类打开具有非空日志文件的文件,那么您知道写入被中断,您可以从日志文件中读取最后写入的位置并 fseek 到那个地方。您丢失了最后的部分写入,但文件不应损坏。

不幸的是,ftruncate() 似乎是异步的。在实践中,即使我在 ftruncate 之后调用 fflush() 和 fsync(),我也会看到日志在进行大量写入时增长到数百字节。它最终总是以 0 结束,但我希望始终看到它的大小为 0 或大小为 8。

是否可以使 ftruncate 完全同步?或者有没有更好的方法来使用期刊?

【问题讨论】:

在恢复日志的过程中如果再次断电怎么办? "有没有更好的方法来使用期刊?" - 取决于您的恢复要求。将一些“下一个块应该是 N 字节”消息写入您的数据文件将避免需要单独的日志(以及磁 HDD 上缓慢的磁头重新定位),前提是在恢复情况下您有时间从头开始重新扫描文件 - 沿着块跳转,或者在从文件末尾向后扫描时可以将此类下一个块-N字节的内容与其他内容区分开来。对于期刊来说,内存映射可能也更优雅一些。 @Kerrek - 日志恢复基本上包括放置写入位置,以便覆盖最后的部分写入。因此,它不需要对数据文件进行任何写入。如果在日志恢复过程中电源出现故障,那很好……下次启动时,您只需恢复日志即可。 【参考方案1】:

ftruncate() 不会更改文件描述符在文件中的写入偏移量。如果您在调用ftruncate() 后保持文件打开并写入下一个长度,那么文件的偏移量仍在增加。当您写入时,它会将文件的长度重置为偏移量,然后将您的字节写入那里。

您可能想要做的是在调用ftruncate() 之后调用lseek(fd, 0, SEEK_SET),这样下一次对文件的写入将发生在文件的开头。

【讨论】:

以上是关于ftruncate() 是异步的吗?的主要内容,如果未能解决你的问题,请参考以下文章

23Linux truncate ftruncate函数

k6 http调用是异步的吗?

Promise 构造函数回调是异步执行的吗?

ReactPHP 真的是异步的吗?

IQueryable 和 IQueryable<T> 是异步的吗?

node.js 的 console.log 是异步的吗?