默认写入行为 - O_TRUNC 或 O_APPEND?

Jet*_*lue 6 c unix linux file-descriptor system-calls

当您open使用访问模式O_WRONLYO_RDWR. 文件是以追加模式还是截断模式打开的?从手册页

参数标志必须包括以下访问模式之一: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 );
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*ica 10

两者都不。

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

  • O_TRUNC 如果文件存在,则会导致文件被截断。

  • O_APPEND导致写入附加到文件末尾而不是在开头覆盖。这个标志是持久的。如果您将光标移到别处来读取数据,它总是在每次写入之前重新定位到文件的末尾。

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

  • 注意 [根据 POSIX,您可以使用 `pwrite()`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html) 写入文件中的任何位置,即使它是用 ` 打开的O_APPEND`:“`pwrite()`函数应与`write()`等效,不同之处在于它写入给定位置并且不更改文件偏移量(无论是否设置了`O_APPEND`)。这允许使用“O_APPEND”打开的文件以原子方式附加数据或以原子方式写入任意偏移量。不幸的是,[`pwrite()` 在 Linux 上被破坏了](http://man7.org/linux/man-pages/man2/pwrite.2.html#BUGS) (3认同)

dbu*_*ush 6

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

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

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