繁体   English   中英

在C ++中运行fwrite

[英]working of fwrite in c++

我试图在写入文件时模拟比赛条件。 这就是我在做什么。

  1. 在process1中以附加模式打开a.txt
  2. 在process1中写“ hello world”
  3. 在process1中打印ftell,为11
  4. 使process1进入睡眠状态
  5. 在process2中以附加模式再次打开a.txt
  6. 在process2中写“ hello world”(正确地附加到文件末尾)
  7. 在process2中打印ftell,为22(正确)
  8. 在process2中写入“再见世界”(正确地附加到文件末尾)。
  9. process2退出
  10. process1恢复,并打印其ftell值11。
  11. 用process1编写“ bye world” ---我假设process1的ftell是11,这应该覆盖该文件。

但是,对process1的写入正在写入文件的末尾,并且在各进程之间的写入没有争用。

我正在使用fopen作为fopen("./a.txt", "a+)

谁能说出这种现象的原因,以及如何在写入文件时模拟竞争条件?

process1的代码:

#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include "time.h"
using namespace std;
int main()
{

    FILE *f1= fopen("./a.txt","a+");
    cout<<"opened file1"<<endl;
    string data ("hello world");
    fwrite(data.c_str(), sizeof(char), data.size(),  f1);
    fflush(f1);
    cout<<"file1 tell "<<ftell(f1)<<endl;
    cout<<"wrote file1"<<endl;
    sleep(3);
    string data1 ("bye world");;
    cout<<"wrote file1 end"<<endl;
    cout<<"file1 2nd tell "<<ftell(f1)<<endl;
    fwrite(data1.c_str(), sizeof(char),  data1.size(),  f1);
    cout<<"file1 2nd tell "<<ftell(f1)<<endl;
    fflush(f1);
    return 0;
}

在process2中,我已注释掉sleep语句。

我正在使用以下脚本运行:

./process1 &
sleep 2
./process2 &

谢谢你的时间。

以追加模式进行写入是原子操作。 这就是为什么它不会破裂。

现在...如何破解?

尝试通过内存映射文件并从两个过程中写入内存。 我很确定这会打破它。

编写者代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BLOCKSIZE 1000000

int main(int argc, char **argv)
{
    FILE *f = fopen("a.txt", "a+");
    char *block = malloc(BLOCKSIZE);

    if (argc < 2)
    {
    fprintf(stderr, "need argument\n");
    }
    memset(block, argv[1][0], BLOCKSIZE);
    for(int i = 0; i < 3000; i++)
    {
    fwrite(block, sizeof(char), BLOCKSIZE, f);
    }
    fclose(f);
}

阅读器功能:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BLOCKSIZE 1000000

int main(int argc, char **argv)
{
    FILE *f = fopen("a.txt", "r");
    int c;
    int oldc = 0;
    int rl = 0;

    while((c = fgetc(f)) != EOF)
    {
    if (c != oldc)
    {
        if (rl)
        {
        printf("Got %d of %c\n", rl, oldc);
        }
        oldc = c;
        rl = 0;
    }
    rl++;
    }

    fclose(f);
}

我先运行./writefile A & ./writefile B然后运行./readfile

我懂了:

Got 1000999424 of A
Got 999424 of B
Got 999424 of A
Got 4096 of B
Got 4096 of A
Got 995328 of B
Got 995328 of A
Got 4096 of B
Got 4096 of A
Got 995328 of B
Got 995328 of A
Got 4096 of B
Got 4096 of A
Got 995328 of B
Got 995328 of A
Got 4096 of B
Got 4096 of A
Got 995328 of B
Got 995328 of A
Got 4096 of B
Got 4096 of A
Got 995328 of B
Got 995328 of A

如您所见,A和B的长距离运行不错,但它们的长度不完全是1000000个字符,这就是我写的大小。 经过第一次试运行之后,整个文件的大小较小,只有7GB。

供参考:Fedora Core 16,在lvm,AMD PhenomII四核处理器,16GB RAM之上具有我自己编译的3.7rc5内核,gcc 4.6.3,x86-64和ext4

我很确定您不能依靠这种行为,但是在某些系统上它可能会可靠地工作。 如果您“足够努力”,则从两个不同的进程写入同一文件可能迟早会引起问题。 索德定律说,这恰恰是您的老板检查软件是否正常工作,客户接受已出售系统的交付时间,定稿要花很长时间才能完成的报告或其他重要时间的时候。

您尝试中断或查看的行为取决于您正在使用的操作系统,因为写入文件是系统调用。 关于您告诉我们的第一个文件描述符不覆盖第二个进程写的内容的事实,您在两个进程中都以追加模式打开文件的事实可能在实际写入ftell值之前就已经实现了。

您是否尝试对标准的打开和写入功能执行相同的操作? 可能也会很有趣。

编辑:C ++参考文档在此处说明了有关fopen附加选项的信息 :“追加/更新:打开文件进行更新(用于输入和输出),所有输出操作均在文件末尾写入数据。重新定位操作(fseek,fsetpos) ,快退)会影响下一个输入操作,但输出操作会将位置移回文件末尾。” 这解释了您观察到的行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM