mmap
(MAP_ANONYMOUS
で使用する場合 ) プロセスの仮想アドレス空間内のどこにでも配置でき、後で割り当てを解除できる RAM のチャンクを割り当てます (munmap
を使用) ) 他のすべての割り当てとは無関係です。
brk
仮想アドレス空間の単一の連続した「アリーナ」の終了アドレスを変更します。このアドレスが増加すると、アリーナにより多くのメモリが割り当てられ、減少すると、アリーナの最後でメモリの割り当てが解除されます。したがって、brk
で割り当てられたメモリ アリーナの最後にアドレスの連続範囲がある場合にのみ、オペレーティング システムにリリースできます。 このプロセスではもう必要ありません。
brk
の使用 小さな割り当ての場合、および mmap
大きな割り当ての場合、小さな割り当てはすべて同じ寿命を持つ可能性が高く、大きな割り当ては他の割り当ての寿命と相関しない寿命を持つ可能性が高いという仮定に基づくヒューリスティックです。そのため、大きな割り当てはシステム プリミティブを使用して他のものから独立して割り当てを解除できるようにし、小さな割り当てはそうでないプリミティブを使用します。
このヒューリスティックはあまり信頼できません。 malloc
の現在の世代 私の記憶が正しければ、実装は brk
で完全にあきらめました mmap
を使用 全てにおいて。 malloc
あなたが見ていると思う実装 (あなたのタグに基づく GNU C ライブラリーのもの) は非常に古く、主に使用され続けています。>おそらく しかし、確かに
では、大きなサイズのメモリを割り当てるときに、malloc が mmap を呼び出すのはなぜでしょうか?
簡単な答えは、効率の向上です。 Linux の新しい実装、およびそれらに付属する更新されたメモリ割り当てアルゴリズムについて。ただし、これは非常に実装に依存するトピックであり、議論されている特定の Linux OS のヴィンテージやフレーバーが異なると、その理由と理由が大きく異なることに注意してください。
これは、低レベルのパーツ mmap()
に関するかなり最近の記事です。 そして brk()
Linux メモリ割り当てで再生します。また、それほど最近ではありませんが、関連性のある Linux Journal の記事には、ここでのトピックに非常に適した内容が含まれています。これには次のようなものがあります:
非常に大きな要求の場合、malloc() は mmap() システム コールを使用して、アドレス指定可能なメモリ空間を見つけます。 このプロセスは、メモリの断片化による悪影響を軽減するのに役立ちます メモリの大きなブロックが解放されますが、それらの間にある最近割り当てられた小さなブロックと割り当てられたスペースの最後によってロックされます。この場合、実際には、ブロックが brk() で割り当てられていれば、プロセスがブロックを解放したとしても、システムは使用できないままでした。
(私のものを強調)
brk()
について :
ちなみに、"...mmap() は Unix の初期のバージョンには存在しませんでした。brk()
当時、プロセスのデータ セグメントのサイズを増やす唯一の方法でした。 mmap() を備えた Unix の最初のバージョンは 80 年代半ばの SunOS で、最初のオープンソース バージョンは 1990 年の BSD-Reno でした。 "。それ以来、メモリ割り当てアルゴリズムの最新の実装は、多くの改良を加えてリファクタリングされ、brk()
を使用する必要性が大幅に減少しました。 .