プロセスが多くのメモリを消費することが何であるかを調べようとして読みました/proc/pid/smaps
(ここでpidはプロセスのpidです)。
私を混乱させるのは、一部の項目に名前がないことです。たとえば、
4805d000-4805e000 rwxp 0001d000 00:0b 19674210 /lib/ld-2.6.so
Size: 4 kB
Rss: 4 kB
Pss: 4 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 4 kB
Referenced: 4 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
4805e000-4805f000 ---p 00000000 00:00 0
Size: 4 kB
Rss: 0 kB
Pss: 0 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
4805f000-4885e000 rwxp 00000000 00:00 0
Size: 8188 kB
Rss: 8188 kB
Pss: 8188 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 8188 kB
Referenced: 8188 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
上記の最初の項目には名前がありますが、/lib/ld-2.6.so
2番目と3番目の項目には名前はありません。それでは、名前のない項目は何ですか?どのライブラリがそのライブラリを作成したかを確認する方法は?
疑問に思って、私のプログラムで何がメモリを消費しているのかを調べようとする他のもの(valgrind以外)がありますか?
カーネルコードを詳しく見た後、これらの項目は実際にはどのファイル(fs/proc/task_mmu.c)にもマップできないことがわかりました。しかし、質問は残っています。それは何ですか? mmap()をメモリ割り当て方法として使用しますか?
答え1
名前のない領域は十分に大きくなって作成できますmalloc
。
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int *ip;
char *before, *after;
asprintf(&before, "cat /proc/%d/smaps > before", getpid());
asprintf(&after, "cat /proc/%d/smaps > after", getpid());
system(before);
ip = malloc(9999999);
if (!ip) abort();
system(after);
return 0;
}
図からわかるように
$ CFLAGS=-g make ilikebigmallocs
cc -g ilikebigmallocs.c -o ilikebigmallocs
$ ./ilikebigmallocs
$ diff before after
64a65,80
> 7f97425ac000-7f9742f36000 rw-p 00000000 00:00 0
> Size: 9768 kB
> Rss: 4 kB
...
したがって、少なくともあなたの領域のいくつかは、おそらくmalloc
同様のもの(ビハインドストーリーと呼ばれるmmap
)によって作成された可能性があります。strace
(またはsysdig
)以下を記録できます。
$ strace -e trace=memory -o blah ./ilikebigmallocs
$ awk '/^mmap/{print $NF}' blah
0x7fc6193b1000
0x7fc6193a6000
...
$ grep 7fc6193b1000 after
7fc6193b1000-7fc6193b2000 rw-p 00000000 00:00 0
$
メモリ不足のプロセスで特定のコードの特定のバックアップをgdb
処理するためにmallocトラッカーや他のものを使用できるようです。mmap