2

現在、Windows のCreateFileMappingメカニズムを使用してプロセス間通信を実装しようとしています。最初に CreateFileMapping でファイル マッピング オブジェクトを作成し、次に MapViewOfFile で実際のデータへのポインターを作成する必要があることはわかっています。次に、この例では、CopyMemory を使用してデータを mapfile に入れます。

私のアプリケーションには、別のプロセスに送信したい画像バッファ (1 MB の大きさ) があります。そこで、画像へのポインターを照会し、画像バッファー全体を mapfile にコピーします。しかし、これが本当に必要なのだろうか。画像バッファデータを指す共有メモリ内の実際のポインタをコピーすることはできませんか? 少しやってみましたがうまくいきませんでした。

4

6 に答える 6

8

プロセスが異なれば、アドレス空間も異なります。あるプロセスの有効なポインタを別のプロセスに渡すと、おそらく 2 番目のプロセスのランダム データを指します。したがって、すべてのデータをコピーする必要があります。

于 2009-03-30T15:25:20.827 に答える
8

Boost::interprocessを使用することを強くお勧めします。この種のものを管理するための多くの利点があり、特定の Win32 機能を使用する他のプロセスと相互運用する必要がある場合に備えて、いくつかの特別な Windows 専用機能も含まれています。

最も重要なことは、通常のポインタではなくオフセット ポインタを使用することです。オフセット ポインターは、基本的には相対ポインターです (ポインターの位置とポイント先の位置の差を格納します)。これは、2 つのポインターが異なるアドレス空間にマップされていても、マッピングの構造が同一である限り問題がないことを意味します。

オフセット スマート ポインターを使用してあらゆる種類の複雑なデータ構造を使用してきましたが、それは魅力的に機能しました。

于 2009-03-30T15:29:17.760 に答える
3

共有メモリは、データの送受信を意味するものではありません。違反のないプロセス数に対して作成されたメモリです。そのためには、データが破損しないように、ロックなどのメカニズムに従う必要があります。

プロセス 1 で:

CreateFileMapping(): 共有メモリ ブロックがまだ存在しない場合は、最後のパラメーターで指定された名前で共有メモリ ブロックを作成し、成功した場合はハンドル (ポインターと呼ぶこともできます) を返します。

MapViewOfFile(): この共有ブロックをプロセス アドレス空間にマップ (インクルード) し、ハンドルを返します (ここでもポインタと言えます)。

によって返されたこのポインターMapViewOfFile()を使用すると、その共有ブロックにアクセスできます。

プロセス 2 で:

OpenFileMapping(): によって共有メモリ ブロックが正常に作成されたCreateFileMapping()場合は、同じ名前 (共有メモリ ブロックの作成に使用された名前) で使用できます。

UnmapViewOfFile(): マップを解除します (そのプロセス アドレス空間から共有メモリ ブロックを削除できます)。共有メモリの使用 (アクセス、変更など) が終了したら、この関数を呼び出します。

Closehandle(): 最後にプロセスから共有メモリ ブロックをデタッチするには、引数、OpenFileMapping() または CreateFileMapping() によって返されるハンドルを指定してこれを呼び出します。

これらの関数は単純に見えますが、フラグが適切に選択されていない場合、動作はトリッキーです。共有メモリを読み書きする場合は in で指定PAGE_EXECUTE_READWRITECreateFileMapping()ます。

共有メモリを正常に作成した後でアクセスしたい場合はいつでも、 in を使用FILE_MAP_ALL_ACCESSMapViewOfFile()ます。

FALSE(親プロセスからハンドルを継承しない)を指定した方がOpenFileMapping()混乱を避けることができます。

于 2012-06-21T03:56:34.747 に答える
2

Windowsの2つのプロセスで同じアドレスを使用するために共有メモリを取得できます。それはいくつかのテクニックで達成可能です。

MapViewOfFileExを使用して、MSDNからの重要な抜粋を次に示します。

提案されたマッピングアドレスが指定されている場合、指定されたアドレスに十分なアドレススペースがある場合、ファイルは指定されたアドレスにマップされます(最も近い64K境界に切り捨てられます)。十分なアドレス空間がない場合、関数は失敗します。

通常、提案されたアドレスは、ファイルを複数のプロセスで同じアドレスにマップする必要があることを指定するために使用されます。これには、アドレス空間の領域が関連するすべてのプロセスで使用可能である必要があります。VirtualAllocまたはVirtualAllocEx関数を使用してメモリを予約するなど、マッピングに使用される領域で他のメモリ割り当てを行うことはできません。

lpBaseAddressパラメーターがベースオフセットを指定している場合、指定されたメモリ領域が呼び出し元のプロセスによってまだ使用されていなければ、関数は成功します。システムは、他の32ビットプロセスのメモリマップトファイルで同じメモリ領域が使用可能であることを保証しません。

別の関連する手法は、読み取り+書き込み+共有とマークされたセクションを持つDLLを使用することです。この場合、OSはほとんどMapViewOfFileEx呼び出しを実行し、DLLをロードする他のプロセスを実行します。

DLLを固定ロードアドレスにマークする必要がある場合があります。当然、再配置可能などではありません。

于 2009-05-29T10:40:19.607 に答える
0

可能であれば、画像データを共有メモリ領域に直接ロード/生成するのが最善です。これにより、メモリのコピーがなくなり、必要な場所に直接配置されます。準備ができたら、他のプロセスに信号を送って、データが始まる共有メモリへのオフセットを与えることができます。

于 2009-03-30T15:37:26.990 に答える
0

ポインタのマーシャリングを使用できます。

于 2009-03-30T15:28:52.970 に答える