セクション4.4でTLPIを読んでいます。
システムコールは、呼び出し側に情報を返すために使用されるバッファにメモリを割り当てません。代わりに、以前に割り当てられた正しいサイズのメモリバッファへのポインタを渡す必要があります。これは、呼び出し側に情報を返すためにメモリバッファを割り当てるいくつかのライブラリ関数とは対照的です。
このような場合、システムコールがメモリを割り当てないのはなぜですか?これは、ユーザーが(不必要に新しいメモリを割り当てるのではなく)既存のバッファを使用できるようにするメモリ最適化ですか?他に理由がありますか?
答え1
多くの開発者は、これがmalloc()
システムコールではないことを忘れています。 Cライブラリ関数です。物理メモリの割り当ては次のように行います。brk
システムコールは非常に異なる動作をします。
malloc()
簡単に言えば、プログラムには、拡張する必要があるデータを格納するために割り当てられたRAMが1つしかありません。必要なら使用brk()
。ただしmalloc
、.を使用してバッファを解放した後は、バッファを簡単に再利用できますfree()
。バッファが解放されると(必ずしもそうではありませんが)、次のようにオペレーティングシステムに返されません。通常はヒープの中央にあります。。
今、あなたの質問に答えてみましょう。システムコールが内部的にバッファを割り当てられないのはなぜですか?
カーネルは、プログラムがデータブロックをどのように使用しているのか分からない。 Cライブラリを使用しているとは考えられません。それ以外の場合は、malloc
データ構造と対話できず、バッファを割り当てるためにどのデータ構造を使用しているかわかりません。これは、解放できるバッファを割り当てることができないことを意味しますfree()
。
理論的には、未使用のアドレス空間にRAMページ全体を割り当てることができますが、それを無効にするにはまったく新しいシステムコールが必要です。これは通常、システムコールを発生free()
させないよりもはるかに高価です。バッファはページ全体よりはるかに小さいので、これは非常に無駄です。
最後に、多くの場合、プログラムの特定の場所にすでにデータが必要になる可能性があることを理解することをお勧めします。データを目的の場所に直接書き込むようにシステムコールに要求できる場合は、コードからデータをコピーしてページを解放する必要はありません。
答え2
カーネルがメモリを割り当てたい場合に呼び出しますmmap()
。呼び出し時にmmap()
必要なフラグを選択する必要があります。割り当てをPROT_EXEC
、MAP_HUGE_2MB
またはに設定しますかMAP_LOCKED
?特定の住所()に割り当てますかMAP_FIXED
?
したがって、割り当てを分離する方が簡単です。これは、すべてのシステムコールでこれらのフラグにパラメータを提供する必要がないことを意味します。
カーネルを使用してメモリ割り当てを解除するには、別のシステムコールが必要ですmunmap()
。
より速くダック-カーネル割り当てを直接使用しない場合は割り当てます。 free()
はシステムコールではないのでmunmap()
。
歴史的な理由もあります。元のUNIXカーネルは、任意のメモリページを割り当てて解放することができませんでした。を呼び出すと、brk()
ヒープメモリのサイズが増えます。ヒープ内のメモリブロックを解放するようにカーネルに要求することはできません。