簡體   English   中英

在FreeBsd和Linux上使用O_APPEND打開文件看起來不像是原子操作?

[英]Open file with O_APPEND on FreeBsd and Linux doesn't look like an atomic operation?

#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;
}

測試環境1:

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

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

測試環境2:

優名
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自由軟件基金會,公司。 請參閱復制條件的來源。 沒有保修; 甚至不是出於適銷性或針對特定目的的適用性。

有些線丟了

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

O_APPEND似乎沒有按照手冊頁中的說明工作。

誰能給我更多有關此的信息?

問題在於,當子級打開文件時,它將被截斷,丟失了父級已寫入文件的數據,從而使父級的計數減少了。 由於孩子必須第二次打開文件,並且文件打開是一項昂貴的操作,因此它可能永遠是計數少的父級。 如果將第一個打開位置移動到只有父打開位置,則時間會有所不同; 有時孩子的條目可能會更少。

修改后的代碼:

#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
$

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM