web-dev-qa-db-ja.com

mmap()を使用してプロセス間でメモリを共有する

私はLinux2.6を使用しています。メッセージパッシングモードの簡単な実装を通じて、2つのプロセスが(共有メモリを使用して)データの交換をシミュレートする環境があります。

(フォークの後に)作成されたメモリマップ領域に構造体(メッセージ)を書き込むクライアントプロセス(サーバーである親からフォークされたもの)があります。

message *m = mmap(NULL, sizeof(message), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)

次に、このポインタは、サーバーとクライアントプロセスに共通の別の共有メモリ領域のキュー(リンクリストの形式)に書き込まれます(上記の同じコードでフォークの前に作成された場合)。次に、この領域はサーバーによって読み取られ、サーバーはメッセージへのポインターを取得して処理します。

問題は、* mがfork()の後に作成され、サーバープロセスが指定されたメモリ位置にアクセスしようとすると、セグメンテーションエラーが発生することです。クライアントが作成した後、そのメモリ領域をサーバーPOSTフォークに接続することは可能ですか?

注:通常、クライアントがサーバーに送信するメッセージの数がわからないため、フォークする前に(そしてサーバーと共有する前に)メッセージへのポインターをmmapしたくありません。複数のクライアントプロセスがあるため、クライアントがメッセージを送信する必要がある場合にのみ共有メモリの新しいブロックを作成し、サーバーがそのメッセージを受信した後でマップを解除したいと思います。

注:これは学術目的です。これがこの問題を解決する最善の方法ではないことはわかっていますが、この方法に従う必要があります。

前もって感謝します!

20
Andrea Sprega

クライアントが作成した後、そのメモリ領域をサーバーPOSTフォークに接続することは可能ですか?

_MAP_ANONYMOUS|MAP_SHARED_マップされたメモリには、そのmmap()呼び出しを実行するプロセスまたはその子プロセスによってのみアクセスできます。 anonymousであるため、そのメモリを他の場所から参照できないため、別のプロセスが同じメモリをマップする方法はありません。

shm_open()呼び出しを使用すると、無関係のプロセスによって参照およびマッピングできるnamed共有メモリを作成できます。

27

2018年以降にこの質問を読んでいる人のためだけに。解決策は、memfd_createを使用して匿名ファイルを作成し、unixソケットを使用してこのファイルハンドルを他のプロセスに渡すことです。

memfd_createはLinuxのみのシステムコールです

9
Lothar

それはうまくいきません。

Fork()の後にマッピングを作成すると、他の関連するプロセスと同じにはなりません。

このようにポインタを共有することは想定できません。

本当にこの方法で実行したい場合(私はお勧めしません!)、fork()の前に大きな領域をmmapしてから、適切なサイズのバッファーを何らかの方法で割り当てます(もちろん、他のプロセスとの競合状態はありません!)。 )そしてそれらのポインタを渡します。

フォークの後にmmap()を呼び出す2つの関連するプロセスは、異なるメモリを指す同じポインタを返す場合があります。実際、これは非常に可能性が高いです。

6
MarkR