【问题标题】:Default write behaviour - O_TRUNC or O_APPEND?默认写入行为 - O_TRUNC 还是 O_APPEND?
【发布时间】:2020-05-10 04:43:12
【问题描述】:

当您open 访问模式为O_WRONLYO_RDWR 的文件时,默认行为是什么。文件是以追加模式还是截断模式打开的?来自man pages

参数标志必须包括以下访问模式之一: O_RDONLY、O_WRONLY 或 O_RDWR。
...
此外,零个或多个文件创建标志和文件状态标志可以在标志中按位或运算。

这听起来像 O_APPENDO_TRUNC 标志是可选的。那么下面是做什么的呢?

void main ( void )
{
    int fd = open( "foo.txt", O_WRONLY );

    write( fd, "hello", 5 );

    close( fd );
}

【问题讨论】:

  • 您可以尝试比询问更容易。此外,由于这些位是 OR'd,根据手册页,只需查看两个定义的值(或询问您的调试器),看看哪个是零。

标签: c linux unix system-calls file-descriptor


【解决方案1】:

都没有。

  • 默认情况下,打开文件时光标位于开头。写入会覆盖文件开头的字节。

  • O_TRUNC 会导致文件在存在时被截断。

  • O_APPEND 导致写入追加到文件末尾,而不是在开头覆盖。这个标志是持久的。如果您将光标移至其他位置以读取数据,则每次写入前它始终会重新定位到文件末尾。

标志是正交的并且不相互排斥。如果您想最初截断文件并确保所有以后的写入始终是附加的,您甚至可以将它们组合起来。

【讨论】:

  • 注意per POSIX, you can use pwrite() 写入文件中的任何位置,即使它是用O_APPEND 打开的:“pwrite() 函数应等效于write(),除了它写入一个给定位置并且不会更改文件偏移量(无论是否设置了O_APPEND)。”这允许使用O_APPEND 打开的文件以原子方式附加数据或以原子方式将数据写入任意偏移量。不幸的是,pwrite() is broken on Linux
  • @AndrewHenle:谢谢你提醒我!自从我第一次听说这个 WONTFIX 错误以来,我一直对它感到愤怒,现在有了一个带有标志参数的 pwritev2 系统调用,我认为它最终可以在不破坏内核 API 稳定性的情况下修复。未经测试的补丁添加了用户空间pwrite函数可以传递的选项来修复它:ix.io/28aG
【解决方案2】:

当单独使用O_WRONLY标志时,它打开文件进行写入,保留现有文件内容,并将文件指针放在文件开头。任何写入都会覆盖现有内容。

如果您使用lseek 重新定位文件指针,后续写入将发生在重新定位的偏移处。

此行为与 O_TRUNC 形成对比,后者在打开文件时截断文件内容,而 O_APPEND 则强制所有写入发生在文件末尾。

【讨论】:

    猜你喜欢
    • 2023-04-04
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    • 2019-09-26
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 2014-07-20
    相关资源
    最近更新 更多