gpt4 book ai didi

c - 在 FreeBsd 和 Linux 上使用 O_APPEND 打开文件看起来不像是原子操作?

转载 作者:太空宇宙 更新时间:2023-11-04 04:40:26 24 4
gpt4 key购买 nike

#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#define BUFSIZE 1024*1024*100
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
int main()
{
pid_t pid;
int pfd = open("data.txt", O_CREAT|O_RDWR|O_TRUNC|O_APPEND, FILE_MODE);
if ((pid = fork()) < 0)
{
printf("errr fork\n");
exit(0);
} else if (pid == 0)
{
int cfd = open("data.txt", O_CREAT|O_RDWR|O_TRUNC|O_APPEND, FILE_MODE);
for (int i = 0; i < 1000000; ++i)
if (write(cfd, "child\n", 6) == -1)
{
printf("err in child\n");
exit(0);
}

exit(0);
}
for (int i = 0; i < 1000000; ++i)
if (write(pfd, "parent\n", 7) == -1)
{
printf("error in parent\n");
exit(0);
}
return 0;
}

测试环境一:

uname -a
FreeBSD freebsd 10.0-RELEASE-p12 FreeBSD 10.0-RELEASE-p12 #0:UTC 2014 年 11 月 4 日星期二 05:07:17 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64

clang -v
FreeBSD clang 版本 3.3 (tags/RELEASE_33/final 183502) 20130610目标:x86_64-unknown-freebsd10.0线程模型:posix

测试环境2:

uname -a
Linux debian 3.2.0-4-amd64 #1 SMP Debian 3.2.63-2+deb7u1 x86_64 GNU/Linux

gcc --version
gcc (Debian 4.7.2-5) 4.7.2版权所有 (C) 2012 Free Software Foundation, Inc.这是免费软件;有关复制条件,请参阅来源。没有保修单;甚至不是为了特定目的的适销性或适用性。

部分线路丢失

$ sort data.txt | uniq -c
1000000 child
982937 parent

O_APPEND 似乎没有像手册页所说的那样工作。

谁能给我更多关于这方面的信息?

最佳答案

问题在于,当子进程打开文件时,它会截断文件,丢失父进程已经写入文件的数据,从而使父进程计数不足。它很可能永远是计数较短的父项,因为子项必须第二次打开文件,而文件打开是一项昂贵的操作。如果第一个打开被移动,所以它只在父级中,那么时间就会不同;有时 child 的条目可能会更少。

修改后的代码:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

int main(void)
{
pid_t pid;
int pfd = open("data.txt", O_CREAT | O_RDWR | O_TRUNC | O_APPEND, FILE_MODE);
if ((pid = fork()) < 0)
{
printf("errr fork\n");
exit(0);
}
else if (pid == 0)
{
int cfd = open("data.txt", O_CREAT | O_RDWR | O_TRUNC | O_APPEND, FILE_MODE);
for (int i = 0; i < 1000000; ++i)
{
char buffer[32];
snprintf(buffer, sizeof(buffer), "child%07d\n", i);
if (write(cfd, buffer, strlen(buffer)) == -1)
{
printf("err in child\n");
exit(0);
}
}
}
else
{
for (int i = 0; i < 1000000; ++i)
{
char buffer[32];
snprintf(buffer, sizeof(buffer), "parent%07d\n", i);
if (write(pfd, buffer, strlen(buffer)) == -1)
{
printf("error in parent\n");
exit(0);
}
}
}
return 0;
}

有一次我运行它,开始输出:

parent0000052
parent0000053
parent0000054
parent0000055
parent0000056
parent0000057
parent0000058
parent0000059
parent0000060
parent0000061
parent0000062
parent0000063
parent0000064
child0000000
parent0000065
child0000001
parent0000066
child0000002
parent0000067

因此,在子文件截断文件 (0..51) 之前,父文件执行了 52 次写入。计数一致:

$ grep -o -E 'child|parent' data.txt | sort | uniq -c
1000000 child
999948 parent
$

关于c - 在 FreeBsd 和 Linux 上使用 O_APPEND 打开文件看起来不像是原子操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27075299/

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