2

ファイルへの書き込みで競合状態をシミュレートしようとしています。これが私がやっていることです。

  1. process1 の追加モードで a.txt を開く
  2. process1 で「hello world」を書く
  3. 11 であるプロセス 1 の ftell を出力します。
  4. プロセス 1 をスリープ状態にする
  5. process2 の追加モードで a.txt を再度開きます
  6. process2 に「hello world」を書き込む (これはファイルの最後に正しく追加されます)
  7. 22 であるプロセス 2 の ftell を出力します (正しい)
  8. process2 に「bye world」と書き込みます (これはファイルの最後に正しく追加されます)。
  9. プロセス 2 が終了します
  10. process1 が再開し、その ftell 値である 11 を出力します。
  11. process1 で「bye world」を書き込む --- process1 の ftell が 11 であるため、ファイルが上書きされるはずです。

ただし、プロセス 1 の書き込みはファイルの末尾への書き込みであり、プロセス間での書き込みの競合はありません。

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 &

御時間ありがとうございます。

4

4 に答える 4

2

ライターコード:

#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、自分でコンパイルした 3.7rc5 カーネル、gcc 4.6.3、x86-64、lvm の上に ext4、AMD PhenomII クアッド コア プロセッサ、16GB の RAM

于 2012-12-22T02:04:01.693 に答える
1

ファイルへの書き込みはシステムコールであるため、中断または表示しようとしている動作は、作業しているOSによって異なります。2番目のプロセスが書き込んだものを上書きしないように最初のファイル記述子について私たちに言ったことについて、両方のプロセスで追加モードでファイルを開いたという事実は、実際に書き込む前に ftell 値を実現した可能性があります。

標準の open 関数と write 関数で同じことをしようとしましたか? こちらも面白いかも。

編集: C++ リファレンス ドキュメントでは、ここでfopen 追加オプションについて説明しています: 、巻き戻し) は次の入力操作に影響しますが、出力操作は位置をファイルの最後に戻します。」これは、観察した動作を説明しています。

于 2012-12-22T01:34:56.123 に答える