gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 16:30:27 25 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/10650861/

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