作为标题,同时指定O_APPENDO_TRUNC时,打开时不会首先截断文件。

因此,当指定O_APPEND时,如何仍然首先截断文件?



@更新:

O_APPENDO_TRUNC可以完美地协同工作,这是我先前代码中的错误。



关于原子

以下代码证明O_APPEND通过将offset设置为在原子系统调用内自动结束,从而确保每个write()中的追加操作都是原子的。

// atomic append
// TLPI exercise 5.3

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int atomic_append(int argc, char *argv[]) {
    char *buf = "a";
    int opt;
    if(argc < 3) {
        printf("command format: %s\n", "atomic_append <filename> <byte-count> [x]");
        return -1;
    }
    char *fp = argv[1];
    int bc = atoi(argv[2]);
    int flag_append = 1;

    if(argc >=4 && strcmp(argv[3], "x")==0) {
        flag_append = 0;
    }

    int fd = open(fp, O_RDWR | O_CREAT | O_TRUNC | (flag_append?O_APPEND:0), 0644);
    int i=0;
    while(i++ < bc) {
        if(!flag_append)  {
            lseek(fd, 0, SEEK_END);
        }
        write(fd, buf, 1);
    }
    close(fd);

    return 0;
}

int main(int argc, char *argv[]) {
    atomic_append(argc, argv);
    return 0;
}


编译和运行的步骤:


编译为a.out
./a.out a1 100000 & ./a.out a1 100000
./a.out a2 100000 x & ./a.out a2 100000 x
ll -h a*


然后您可以看到a1和a2的大小不同。
这是TLPI练习5.3中的练习。

最佳答案

O_APPENDO_TRUNC可以正常工作。如果没有,我会怀疑您的操作系统中存在错误(或更可能是您的代码中存在错误)。

这是一个简单的测试程序,可以在MacOS,OpenBSD和两个不同版本的Linux上正常运行:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <err.h>

#define FN "truncateme"

int
main(int argc, char **argv)
{
    char buf[16];
    ssize_t r;
    int fd;

    if ((fd = open(FN, O_RDWR|O_CREAT|O_TRUNC, 0600)) == -1)
        err(1, "open 1 ");

    if (write(fd, "foo", 3) != 3)
        err(1, "write 1");

    close(fd);

    if ((fd = open(FN, O_RDWR|O_TRUNC|O_APPEND, 0600)) == -1)
        err(1, "open 2");

    if (write(fd, "1", 1) != 1)
        err(1, "write 2");

    close(fd);

    if ((fd = open(FN, O_RDONLY)) == -1)
        err(1, "open 3");

    if ((r = read(fd, buf, 16)) != 1)
        errx(1, "read %d != 1", (int)r);

    return 0;
}


Here is the POSIX description of open注意它说的是“可以使用以下任何组合”,并且该列表同时包含O_APPENDO_TRUNC

我真的不知道O_TRUNC如何与O_APPEND交互,因为第一个只是在打开时告诉操作系统该文件的处理方式,而O_APPEND则告诉操作系统该做什么。调用writewritev函数时要执行的操作。

另外,为消除混乱,其他答案也给了您。 O_APPEND does guarantee atomicity of the write:“如果设置了文件状态标志的O_APPEND标志,则应在每次写操作之前将文件偏移设置为文件的末尾,并且在更改文件偏移和写操作之间不得进行任何中间文件修改操作”。

为了消除进一步的混乱,我在关于POSIX下文件操作的原子性的评论中看到了this part of the standard is relevant.

09-26 18:29