gpt4 book ai didi

c - `write(2)` 到本地文件系统的原子性

转载 作者:行者123 更新时间:2023-11-30 16:31:09 28 4
gpt4 key购买 nike

显然 POSIX 指出

Either a file descriptor or a stream is called a "handle" on the open file description to which it refers; an open file description may have several handles. […] All activity by the application affecting the file offset on the first handle shall be suspended until it again becomes the active file handle. […] The handles need not be in the same process for these rules to apply. -- POSIX.1-2008

If two threads each call [the write() function], each call shall either see all of the specified effects of the other call, or none of them. -- POSIX.1-2008

我对此的理解是,当第一个进程发出write(handle, data1, size1) 和第二个进程问题write(handle, data2, size2),写入可以按任何顺序发生,但data1data2 必须都是原始且连续的。

但是运行以下代码给了我意想不到的结果。

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
die(char *s)
{
perror(s);
abort();
}

main()
{
unsigned char buffer[3];
char *filename = "/tmp/atomic-write.log";
int fd, i, j;
pid_t pid;
unlink(filename);
/* XXX Adding O_APPEND to the flags cures it. Why? */
fd = open(filename, O_CREAT|O_WRONLY/*|O_APPEND*/, 0644);
if (fd < 0)
die("open failed");
for (i = 0; i < 10; i++) {
pid = fork();
if (pid < 0)
die("fork failed");
else if (! pid) {
j = 3 + i % (sizeof(buffer) - 2);
memset(buffer, i % 26 + 'A', sizeof(buffer));
buffer[0] = '-';
buffer[j - 1] = '\n';
for (i = 0; i < 1000; i++)
if (write(fd, buffer, j) != j)
die("write failed");
exit(0);
}
}
while (wait(NULL) != -1)
/* NOOP */;
exit(0);
}

我尝试在 Linux 和 Mac OS X 10.7.4 上运行它并使用 grep -a
'^[^-]\|^..*-'/tmp/atomic-write.log
显示某些写入不连续或重叠 (Linux) 或完全损坏 (Mac OS X)。

open(2) 调用中添加标志 O_APPEND 可以修复此问题问题。很好,但我不明白为什么。 POSIX 说

O_APPEND If set, the file offset shall be set to the end of the file prior to each write.

但这不是这里的问题。我的示例程序从来没有这样做lseek(2) 但共享相同的文件描述,因此共享相同的文件偏移量。

我已经在 Stackoverflow 上读过类似的问题,但它们仍然没有完全回答我的问题。

Atomic write on file from two process并没有具体解决进程共享相同文件描述的情况(而不是同一个文件)。

How does one programmatically determine if “write” system call is atomic on a particular file?说的是

The write call as defined in POSIX has no atomicity guarantee at all.

但如cited above它确实有一些。更重要的是,O_APPEND 似乎触发了这种原子性保证,尽管看起来对我来说,即使没有 O_APPEND,这种保证也应该存在。

您能进一步解释一下这种行为吗?

最佳答案

man 2 write在我的系统上总结得很好:

Note that not all file systems are POSIX conforming.

这是最近的一个引用discussion关于ext4邮件列表:

Currently concurrent reads/writes are atomic only wrt individual pages,however are not on the system call. This may cause read() to return datamixed from several different writes, which I do not think it is goodapproach. We might argue that application doing this is broken, butactually this is something we can easily do on filesystem level withoutsignificant performance issues, so we can be consistent. Also POSIXmentions this as well and XFS filesystem already has this feature.

这清楚地表明 ext4 -- 仅举一个现代文件系统的例子 -- 在这方面不符合 POSIX.1-2008。

关于c - `write(2)` 到本地文件系统的原子性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50752288/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com