2009-04-12 5 views
4

私は同じファイルをメモリマッピングすることで、2つの異なるプロセスが通信できるようにしようとしています。しかし、私はこれにいくつか問題があります。私はこれがopen()呼び出しを使用し、ファイル記述子をmmapに渡す方法と関係があると感じています。mmapをファイルに使用する

ここに私のコードがありますが、何か間違っていますか?

オブジェクト1のコード:

16  FILE* temp = fopen(theSharedFileName, "w"); 
17  fseek(temp, fileSize-1, SEEK_SET); 
18  fprintf(temp, "0"); // make the file a certain size 
19  fseek(temp, 0, SEEK_CUR); 
20 
21  int sharedFileName = fileno(temp); 
... 
31  sharedArea = (MyStruct*)mmap(0, fileSize, 
32   PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, sharedFileName, 0); 

は、私は、オブジェクト1のみがこれまでに一度行われますので、「W」ファイルモードを使用して、私はそれが以前に既存のデータをリセットしたいです。

オブジェクト2のコード:

130  FILE* tempFile = fopen(sharedFileName, "a"); 
131  int theFile = fileno(tempFile); 
... 
135  sharedArea = (MyStruct*)mmap(NULL, fileSize, 
136   PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, theFile, 0); 
+0

あなたはどんな厳しい問題に直面していますか?あなたはobj1がobj1の前にファイルにアクセスしないことを保証できますか? – dirkgently

+0

はい、obj1はより多くのサーバーであり、obj2は後で開始されるクライアントのようなものです。 – samoz

答えて

24

いくつかの問題:高レベルI/O(のfopen()、fseek関数())を混合

  1. 避け、mmapのようないくつかの低レベルの操作()。 fileno()を使用して低レベルのファイル記述子を取得することはできますが、それは同じ場所に到達するのに最も長いルートを取るようなものです。また、mmap()を使うだけで、BSDやPOSIXを越える互換性が失われるため、標準のC入出力関数を使用することで何も得られません。 open()とlseek()を直接使用してください。
  2. メモリマッピングである同じファイルでストリーム形式のI/O(fprintf())を使用することは意味がありません。ファイルをメモリマップするときは、ランダムアクセス(直接インデックス)データとして使用することを暗黙的にシステムに指示します。 fprintf()はストリーム出力用ですが、通常は順次アクセス用に使用します。実際、同じ記述子でfprintf()とfseek()を見るのは普通です(これはポータブルではありませんが、前の項目では移植性を考慮していません)。
  3. 保護はオープンファイル保護と一致する必要があります。 fopen()に "w"を渡していてmmap()にPROT_READ | PROT_WRITE | PROT_EXECを渡しているので、あなたはこの制限に違反しています。これはまた、高レベルI/Oとメモリマッピングを混在させない理由を強調しています。fopen(...,"w")が正しいフラグでファイルを開くことをどうやって保証しますか?これは、Cライブラリの "実装の詳細"とされています。読み取りと書き込みの権限でファイルをメモリマップする場合は、ローレベルのopen(theSharedFileName, O_RDWR)を使用してファイルを開く必要があります。
  4. PROT_WRITEPROT_EXECを一緒に使用しないでください。それは携帯ではないセキュリティ上のリスクです。 W^Xexecutable space protectionについて読む
+0

非常に完全な答えです。 – Anthony

+1

この回答の一部は誤っているようです。 'fprintf'と' fseek'を一緒に移植することができないと思うのは混乱しています。そして、#3とファイルモードに関しては、POSIXは、 'fopen'モード文字列がファイルディスクリプタモードにどのように変換するかを非常に明示しています。実装固有のものではありません。 –

1

他にも述べたように、これにはfopen()とフレンドを使用しないでください。

fprintf()がストリームバッファを持つ可能性があるため、実際にはファイルが変更されない可能性があります。したがって、期待どおりに他のプロセスに表示される可能性があります。 fflush()を追加することもできますが、read()とwrite()はアプリケーションレベルのバッファリングを行わないため、より適切な理由の一部です。

2

C++を使用することができ、ACEまたはBoostのようなライブラリは、低レベルの詳細から守り、IPCの簡単な抽象化を提供します。

関連する問題