2012-08-29 13 views
6

私は、組み込みLinuxシステムで一晩のメモリテストを行っています。 vmstatの使用私は空きメモリが時間とともに徐々に減少することを観察しました。いくつかのによると、の分析では、procfsで、1つのプロセスのヒープはほぼ同じ速度で成長します。私はメモリリークが疑われ、newdeleteが定期的に使用されているコードにいくつかの箇所がありました。しかし、私はの呼び出しに一致することなくnew呼び出しを見ませんでした。 もし割り当て解除されたヒープメモリが/いつ取り戻されるのですか?

は、私は再びメモリテストを実行し、今朝はvmstatの中に記載されている空きメモリがテストが開始されたときに近い値にまで行ってきました次の呼び出し

echo 3 > /proc/sys/vm/drop_caches 

とメモリキャッシュをクリア。

カーネルは定期的に未使用のヒープページを再利用していますか?もしそうなら、上記以外にもこれが行われていますか?おそらく空きメモリが特定のしきい値を下回るとしたら?

+4

未使用のメモリは無駄なメモリなので、他の誰かが使用するまで、linuxはメモリを使います。 – PlasmaHH

+1

あなたは、この明らかに漏れやすいプロセスによって使用されるカーネルヒープまたはヒープについて話していますか? –

+0

@Tom:私はユーザー空間プロセスのヒープについて話しています – waffleman

答えて

5

他にも述べたように、カーネルにメモリを返すのはプロセスの義務です。

は、通常のメモリを割り当てるには2つの方法があります:一定規模以上おmalloc()/newメモリブロック場合は、メモリがmmap()を経由してOSから割り当てとすぐ、それは自由であるとしてeturnedます。より小さいブロックは、sbrkボーダーを上にシフトすることによって、プロセスのデータ領域を増加させることによって割り当てられます。このメモリは、特定のサイズを超えるブロックがそのセグメントの最後に空いている場合にのみ解放されます。

例えば:

a = new char[1000]; 
b = new char[1000]; 

メモリマップ(擬似コード、私は非常によくC++知らない):あなたはa無料、今、あなたは真ん中に穴を持っている場合は

---------------+---+---+ 
end of program | a | b | 
---------------+---+---+ 

を。それは解放することができないので解放されません。 bを解放すると、プロセスのメモリが縮小される場合もあれば、縮小されない場合もあります。未使用の剰余がシステムに戻される。

#include <stdlib.h> 

int main() 
{ 
    char * a = malloc(100000); 
    char * b = malloc(100000); 
    char * c = malloc(100000); 
    free(c); 
    free(b); 
    free(a); 
} 

ような単純なプログラムテストは、(brk値が最初(malloc()ために)増加し、再び減少していることを示している

brk(0)         = 0x804b000 
brk(0x8084000)       = 0x8084000 
brk(0x80b5000)       = 0x80b5000 
brk(0x809c000)       = 0x809c000 
brk(0x8084000)       = 0x8084000 
brk(0x806c000)       = 0x806c000 

あるようstrace出力をもたらしますfree())。

+0

これはどのランタイムライブラリが行いますか? –

+0

@TomTanner、glibcはLinux上のメモリ管理を行います。 –

+0

プログラムは 'sbrk'を使って実際にサイズを減らしますか?私はいつも、完全にフリーのブロックを最後に持っている可能性は低いので、サイズを減らすことは決してないと思っていました。 –

1

カーネルはキャッシュされたメモリページを必要に応じて、つまりシステムがメモリ不足になったときに再利用します。プロセスのヒープ(フリーストア)からのメモリページがOSに返されるかどうかは、プロセスのメモリマネージャの裁量に委ねられます。この場合、C++ライブラリのnew/delete実装です。これは、カーネルが何もしていない完全自発的な操作です。

drop_cachesがこのトリックを行ったことから、プロセスのヒープではなく、メモリをいっぱいにしていたのがカーネルキャッシュであると推測できます。 freeコマンドを使用して、実際にアプリケーションの使用に使用できるメモリの量、espを調べます。 -/+ buffers/cache行が報告されます。

1

プログラム内でdeleteを呼び出すと、プログラムランタイムの一部であるメモリマネージャにメモリが返されます。原則として、これは解放されたメモリをOSに返すように書くことができるが、もしそうであれば驚くだろう。むしろリサイクルされたメモリは、その後のnewの呼び出しのために確保されています。

これはプロセスの仮想メモリであることに注意してください。プログラムの実行中に物理メモリに実際にどのくらい存在しているかは、システム全体の負荷に依存し、オペレーティングシステムによって処理されます。

0

私の知識の範囲内で、mallocとfree(またはnewとdelete)を呼び出すユーザは、使用されていないページをO/Sに返すことはありません。代わりに、メモリが解放されたことを覚えているので、以前に解放されたメモリで満足できるサイズのmalloc/newを実行すると、O/Sに行き、sbrkを使ってより多くの記憶。

したがって、このコード:

for (;;) 
{ 
    struct { char data[200 * 1024 * 1024] } HugeBuffer; 
    HugeBuffer *buff = new HugeBuffer; 
    delete buff; 
} 

は一度200MBのを割り当てます、その後、ちょうど着実に永遠にそのメモリを使用します。元の割り当てでO/Sに1回移動した後、ユーザー空間でループします。

関連する問題