Linux学習記録 - プロセス間通信 (2) 共有メモリ


1. System V 共有メモリ

システムは、ファイル システムから独立した一連の標準であり、システムによる通信のために特別に設計されたカーネル モジュールであり、システム V の IPC 通信メカニズムと呼ばれます。

メモリを共有する主な方法は、無関係な 2 つのプロセスに同じリソースを参照させることです。

1. 原則

プロセスのアドレス空間には、スタックとヒープ領域の間に共有領域があり、ヒープは上に、スタックは下に成長し、重なった領域が共有領域となり、そこにダイナミックライブラリが格納されます。物理メモリ内のスペースを開き、このスペースを共有領域にマップし、このスペースの開始アドレスをユーザーに返します。同様に、別のプロセスも同じことを行うため、2 つのプロセスが物理メモリ内の同じスペースにアクセスできます。

共有されなくなった場合、プロセスはマッピング関係をキャンセルし、ページ テーブルを変更してから、アドレス空間の共有メモリを解放し、最後に物理メモリの共有メモリを解放します。共有される。

2. シミュレーションの実装

コード全体

server.cc ファイルから始めて、次の単語と照合してコードを分析します。

ここに画像の説明を挿入

shmget (System V 共有メモリに適用) はシステム コール インターフェイスです。size は要求されたメモリ ブロックのサイズです。shmflg は大文字で、実際の操作に使用され、コードに記述されます。この関数が正常に作成されると、共有メモリの識別子が返されます。この添字はファイルの添字とは異なるため、実際にはあまり使用されず、ファイルの使用方法がより一般的になります。key パラメータは ftok 関数で設定する必要があり、ftok は渡されたプロジェクト ID とパスを組み合わせてキーを生成します。

共有メモリの原理は上に書きましたが、システム内に共有メモリが 1 つだけあるわけではなく、複数のプロセスがメモリを共有しているわけではないため、システム内には同時に多数のメモリが存在することになります。まずそれらを説明して整理し、共有メモリのすべての属性を保存する構造を作成します。

最下層では、共有メモリの管理が構造体の管理となり、2 つのプロセスが同じデータを取得できる限り、同じ共有メモリにアクセスできます。しかし、システムには大量の共有メモリがあるのに、2 つのプロセスが確実に 1 つのメモリにアクセスできるようにするにはどうすればよいでしょうか? これは ftok 関数のキーです。プロセスは共有メモリを作成し、パスを指定し、ID を渡してキーを形成します。キーは共有メモリの構造に埋められ、別のプロセスも ftok を呼び出します。同じパスと ID を使用する場合、キーも生成され、2 つのキーが一致するため、同じリソースにアクセスする必要があります。

共有メモリに関連するプロセスは終了しましたが、メモリはまだ存在しています。共有メモリの存在を確認するにはどうすればよいですか?

ipcs

「Shared Memory Segments」列を確認するか、-m を追加してこの列だけを確認することもできます。ipcrmで共有メモリを削除できますが、keyやshmidに応じて削除すべきでしょうか?

shmid は、shmget 関数によって返される共有メモリの識別子であり、fd に相当します。キーはシステム内で使用され、共有メモリの i ノードに相当します。Shmid はユーザー レベルで使用されます。命令はシステム インターフェイス層の上のユーザー層にあります。ipcrm -m shmid コマンドを削除します。

shmctl

これも問題を反映しています。共有メモリがプロセスに追従しません。書き込まれたシミュレーション ファイルが実行可能プログラムに生成されると、呼び出しがクリアされ、再度呼び出しが行われます。作成する必要がないため、サーバーは失敗します。再度それを実行すると、クライアントはそれを取得してアップロードできます。共有メモリはオペレーティング システムによって異なります。コマンドの削除に加えて、システムインターフェースを呼び出すこともできます。

共有メモリは作成されますが、直接使用することはできず、shmat関数を使用します。

ここに画像の説明を挿入

ユーザが取得した共有メモリのアドレスは仮想アドレスです。shmat パラメータの shmaddr は、アドレス空間内のどこに配置されるかを参照するため、通常は None に設定され、システムが自動的に実行します。shmflg はメモリ ブロックの属性を設定できます。0 の場合、読み取りおよび書き込みが可能です。

3. 共有メモリのサイズ

上記のコードでは gsize = 4096 に設定されていますが、ipcs -m を使用して実行中のプロセスを表示すると、開いた共有メモリのサイズが 4096 であることがわかります。このサイズは変更できます。共有メモリのサイズは PAGE ページに基づいており、PAGE に対して上向きに配置されます。システムはページ単位でメモリを割り当てます。このページのサイズは 4kb です。これはファイルとディスク データ ブロック、IO の単位。しかし、gsize を 4097 に設定すると、共有メモリのサイズは 4096 * 2 になるはずです。4097 が 4096 を超えるため、PAGE に揃えるルールに従って 4096 を 2 倍する必要がありますが、コマンドによって 4097 になっています。実際、容量は拡張されていますが、システムは確かに 4096 の 2 倍に揃えられていますが、私は 4097 しか使用せず、共有メモリのサイズは 4097 です。

-------------------------------------------------- -------------------------------------------------- --------------------------------------------

4. 共有メモリの特徴

共有メモリはプロセスのアドレス空間にマッピングされており、すでに認識されており、ユーザーは何もする必要がないため、共有メモリはシステム コール インターフェイスを使用しません。この機能があるからこそ、プロセスが通信する際のコピー数を削減できるため、共有メモリは全プロセス間の通信が最も高速になります。

上記のコードによると、クライアントが呼び出さず、共有メモリにコンテンツがなく、サーバーだけが呼び出された場合、サーバー リーダーは常に空の値を読み取って出力し、パイプラインはリーダーをブロックし、待機するまで待機します。ライターは読み取りを続行する前に書き込みを開始するため、共有メモリの保護メカニズム (同期相互排他) はありません。

なぜ共有メモリにはこの致命的な欠点があるのでしょうか? パイプラインはシステム インターフェイスを介して通信し、システム インターフェイスはシステム内で呼び出されたデータを管理します。共有メモリは直接通信します。

おすすめ

転載: blog.csdn.net/kongqizyd146/article/details/130167976