7

私の理解では、UNIX では、メモリが解放されると、メモリはオペレーティング システムに返されず、次の malloc 呼び出しで再び使用されるプロセスにとどまります。

Windowsでは、メモリが実際にオペレーティングシステムに返されることを理解しています。

これら 2 つの方法に大きな違いはありますか? それとも、同じことを行う 2 つの方法が異なるだけですか? また、これら 2 つの方法に長所と短所があるとすれば、それは何ですか?

編集: 明確にしていただきありがとうございます。私はずっと、これは OS の問題だと思っていました (UNIX ライクなシステムではプロセスのサイズが縮小することは決してないように見えますが、Windows では縮小するためです)。

4

9 に答える 9

15

それに関しては、Windows と Unix の間に大きな違いはありません。

どちらにも、2 つのレベルの割り当てがあります。オペレーティング システムは、大きなチャンク (1 ページ以上。x86 では、ページ サイズは通常 4096 バイト) でプロセスにメモリを割り当てます。プロセス内で実行されるランタイム ライブラリは、このスペースを分割し、その一部をコードに割り当てます。

メモリをオペレーティング システムに戻すには、まず、これらの大きなチャンクの 1 つから割り当てられたすべてのメモリをランタイム ライブラリに解放する必要があります。ランタイム ライブラリは、必要に応じて、オペレーティング システムにそのメモリのチャンクを解放するように指示できます。

Linux では、 と がbrkありmmapます。brkプロセスに割り当てられた大きなメモリ チャンクのサイズを制御します。拡大または縮小できますが、一方の端のみです。malloc従来、より多くのメモリを割り当てる必要がある場合はこのメモリのチャンクを拡張し、可能な場合は縮小します。ただし、縮小は簡単ではありません。その割り当ての前にすべてが解放されたとしても、最後に1バイトのタイミングの悪い割り当てが必要であり、縮小できなくなります。これは、「Unix はメモリを解放しない」というミームのソースです。

ただし、匿名もありmmapます。Anonymousmmapはオペレーティング システムにメモリのチャンクを要求します。このチャンクは、プロセス メモリ空間のどこにでも配置できます。このチャンクは、まだ解放されていない後の割り当てがある場合でも、不要になったときに簡単に返すことができます。mallocも使用しますmmap(特に、解放後にメモリのチャンク全体を簡単に返すことができる大規模な割り当ての場合)。

もちろん、Windows と Linux の両方で、ランタイム ライブラリのメモリ アロケータ (またはアロケータ) の動作が気に入らない場合は、独自のものを使用して、オペレーティング システムにメモリを要求し、必要な方法で分割することができます (場合によっては、別のアロケータからメモリを要求しますが、より大きなブロックで)。興味深い用途の 1 つは、タスク (たとえば、Web サーバー要求) に関連付けられたすべてのメモリ用のアロケータを用意することです。このアロケータは、タスクの最後に完全に破棄されます (すべてのピースを個別に解放する必要はありません)。もう 1 つの興味深い用途は、固定サイズのオブジェクト (たとえば、5 バイトのオブジェクト) のアロケーターです。これにより、メモリの断片化が回避されます。

于 2008-10-25T12:40:45.713 に答える
6

以下の内容で、私は Unix よりも Windows について多くのことを知っていることに注意してください ...

いずれにせよ、メモリの割り当てと割り当て解除で実際に何が起こるかは、あなたが説明したものとはまったく異なります。これは、コンピュータが所有する物理メモリと、プログラムの仮想アドレス空間 (プログラムが使用できると考えるメモリ) という 2 つのまったく異なる概念が機能しているためです。

プログラムがオペレーティング システムからより多くのメモリを要求すると、実際に起こっていることは、プログラムで以前は利用できなかった仮想アドレス空間が、プログラムからアクセスできるように設定されているということです。最新のオペレーティング システムは、プロセスが割り当て要求を行うときにプロセスに渡す「実際の」(つまり、物理的な) メモリのプールを持っているだけでは機能しません。実行中のすべてのプログラムの仮想アドレス空間を維持します。プログラムは実際にその仮想アドレス空間の一部にアクセスし、おそらく別のプログラムのアドレス空間の一部をディスク上のスワップファイルにスワップアウトすることにより、これが物理メモリにマップされるようにします。

この例として、Windows では、各スレッドは (デフォルトで) 割り当てられたメガバイトのスタック領域で開始されます。これは、すべてのスレッドが 1 メガバイトのマシンの物理メモリを消費するという意味ではありません。単に、使用できるようにアドレス空間が設定されているということです。この意味で、オペレーティング システムがプログラム メモリを提供し、次にプログラムがそれを返すと考えるのは実際にはうまくいきません。

于 2008-10-25T07:22:12.453 に答える
4

それはすべて、使用する C ランタイム ライブラリによって異なります。特定の UNIX 方式または WINDOWS 方式はありません。各コンパイラ ベンダー (HP、SUN、MS、GNU) には、malloc のロジックを含む独自のランタイム ライブラリが付属しています。malloc の各実装は、OS に応じて同じまたは異なる動作をします。UNIX/LINUX/Windows のいずれも、空きメモリを OS に「実際に戻す」必要はありません。それは高すぎるでしょう(alloc()は非常に小さなチャンクになるため)

最近、mozilla Firefox は *BSD OS から malloc() 実装を借用しました。彼らは、コンパイラ ベンダー (この場合は複数 -- gcc と VC++) が出荷したものとは異なる malloc を使用することを選択しました。彼らは特定の行動を望んでいたので、彼らが望んでいたものを手に入れました。

于 2008-10-25T07:30:59.927 に答える
3

他にも述べたように、これは OS 自体よりも malloc の実装に関連しています。Linux では、glibc を使用すると、メモリは常に特定のサイズを超えて OS に返されます。glibc malloc は大きな割り当て (MMAP_THRESHOLD によって制御される) に mmap を使用し、その場合、free は munmap を呼び出します。これにより、予約されたメモリが自動的に解放されます。そのしきい値を下回ると、brk が使用され、その場合、free はメモリを「返さない」。

上記の説明は正確ではないことに注意してください。正確に言うと、物理メモリ、仮想メモリなどの違いを知る必要があります...これはここでよく説明されています:

http://blogs.msdn.com/oldnewthing/archive/2004/08/22/218527.aspx

于 2008-10-25T08:37:33.193 に答える
2

このメモリ管理の記事から

通常、malloc は解放されたメモリをオペレーティング システムに返しません。プロセスが終了するまで、プロセスによって所有されたままになります。プロセスは、次に追加のメモリを要求するときに再利用できますが、他のメモリが使用できない場合でも、他のプログラムはそのプロセスにアクセスできません。したがって、当然のことながら、プログラムのメモリ フットプリントは、一度に行われる最大の割り当てのサイズです。したがって、必要のないオブジェクト、特に大きなオブジェクトをできるだけ早く解放して、このフットプリントを最小限に抑えることが常に賢明です。

その記事は、Windowsでは、少なくともCプログラムの場合、メモリがOSに返されないことを示唆しています。

したがって、Windows メモリの割り当て解除に関する一般化についてはよくわかりません。

とはいえ、Windowsで低レベルのシステム コール sbrk および mmap/munmap を実装することにより、Microsoft Windows での UNIX メモリ管理のエミュレートを試すことができます。

于 2008-10-25T06:32:28.750 に答える
2

The only operating system where you can't easily give allocated memory back to the system is OS X - quoting Firefox 3 Memory Usage:

After extensive testing and confirmation from Apple employees we realized that there was no way for an allocator to give unused pages of memory back while keeping the address range reserved.. (You can unmap them and remap them, but that causes some race conditions and isn’t as performant.) There are APIs that claim to do it (both madvise() and msync()) but they don’t actually do anything.

于 2008-10-25T08:01:52.127 に答える
1

他の投稿者は、プラットフォーム固有の角度についてコメントしています。しかし、malloc について具体的に尋ねるので、C 標準の内容を見てみましょう。

「free 関数は、ptr が指すスペースの割り当てを解除します。つまり、さらに割り当てられるようにします。」

これは、メモリが OS に返されないという非常に明確な要件のようです。この動作に依存しているプログラムを時折見ます:

int main(void)
{

    void *p = malloc(AS_MUCH_MEMORY_AS_I_WILL_EVER_NEED);

    if (p != 0)
    {
        free(p);
        /* malloc should always work for rest of program */
    }
}

ただし、この質問が comp.lang.c で発生したとき、一部の投稿者はこのセクションを指摘しました。

「malloc 関数は、ヌル ポインターまたは割り当てられた領域へのポインターを返します。」

これは、malloc の呼び出しが失敗する可能性があることを示唆しています。標準の意図は、メモリが OS に返されないようにすることのようですが、言語弁護士の目には、この問題は 100% 確実ではありません。

于 2008-10-25T08:38:03.643 に答える
1

Windows についてはわかりませんが、UNIX では、brk()呼び出しで使用するメモリをアドレス空間に追加するために呼び出しが使用されmalloc()ます。

プロセスが終了するまで、このメモリが OS に返されるのを見たことがありません。通常、これは などのツールで確認できますtop

Windows でも同じ動作になると思いますが、Windows にはこれ以外の割り当て関数がmalloc()あることを知っています (Win32 API の一部)。

于 2008-10-25T06:37:05.493 に答える
0

malloc 関数は、NULL ポインターまたは割り当てられたスペースへのポインターを返します。」

これは、malloc の呼び出しが失敗する可能性があることを示唆しています。標準の意図は、メモリが OS に返されないことであると思われます。

于 2015-03-18T07:21:44.037 に答える