1)shmat()は、ローカルプロセスの仮想メモリを共有セグメントにマップします。この変換は、共有メモリアドレスごとに実行する必要があり、shmアクセスの数に比べてかなりのコストがかかる可能性があります。マルチスレッドアプリケーションでは、追加の変換は必要ありません。共有メモリにアクセスしない通常のプロセスと同様に、すべてのVMアドレスが物理アドレスに変換されます。
共有ページを設定するための初期コスト(呼び出すプロセスでページテーブルにデータを入力する)を除けば、通常のメモリアクセスと比較してオーバーヘッドはありませんshmat()
。ほとんどの種類のLinuxでは、共有メモリ4KBあたり1ページ(4または8バイト)です。 。
ページが共有で割り当てられているか、同じプロセス内で割り当てられているかにかかわらず、(関連するすべての比較に対して)同じコストです。
2)共有メモリセグメントは、カーネルによって何らかの方法で維持される必要があります。パフォーマンスの観点から「どういうわけか」が何を意味するのかわかりませんが、たとえば、shmに接続されているすべてのプロセスが停止しても、shmセグメントはまだ稼働しており、最終的には新しく開始されたプロセスから再度アクセスできます。shmセグメントの存続期間中にカーネルがチェックする必要があるものに関連して、少なくともある程度のオーバーヘッドが必要です。
共有されているかどうかに関係なく、メモリの各ページには「構造体ページ」が添付されており、ページに関するデータが含まれています。項目の1つは参照カウントです。ページがプロセスに渡されると(「shmat」またはその他のメカニズムを介して)、参照カウントが増加します。何らかの方法で解放されると、参照カウントがデクリメントされます。デクリメントされたカウントがゼロの場合、ページは実際に解放されます。それ以外の場合、「それ以上何も起こりません」。
割り当てられた他のメモリと比較して、オーバーヘッドは基本的にゼロです。同じメカニズムがとにかくページの他の目的に使用されます-たとえば、カーネルによっても使用されているページがあり、プロセスが停止した場合、カーネルは、カーネルによってリリースされるまでそのページを解放しないことを知る必要があります。同様に、ユーザープロセス。
「フォーク」が作成されたときにも同じことが起こります。プロセスがフォークされると、親プロセスのページテーブル全体が基本的に子プロセスにコピーされ、すべてのページが読み取り専用になります。書き込みが発生するたびに、カーネルによって障害が発生し、そのページがコピーされます。そのため、そのページのコピーが2つあり、書き込みを行うプロセスは、他のプロセスに影響を与えることなく、そのページを変更できます。子(または親)プロセスが停止すると、もちろん、両方のプロセスがまだ所有しているすべてのページ[書き込まれることのないコードスペースや、おそらく触れられない共通データの束など]は明らかにできません。両方のプロセスが「デッド」になるまで解放されます。繰り返しになりますが、ここでは参照カウントページが役立ちます。これは、各ページの参照カウントのみをカウントダウンするためです。
共有ライブラリでもまったく同じことが起こります。1つのプロセスが共有ライブラリを使用している場合、そのプロセスが終了すると解放されます。ただし、2つ、3つ、または100のプロセスが同じ共有ライブラリを使用する場合、ページが不要になるまでコードをメモリに保持する必要があります。
したがって、基本的に、カーネル全体のすべてのページはすでに参照カウントされています。オーバーヘッドはほとんどありません。