「Linuxカーネルについて」で読んだところによると、mallocがユーザースペースで呼び出されると、カーネルはvm_area_t構造に線形領域を追加するだけで、メモリにスペースを割り当てるのではなく、割り当ての延期と呼ばれ、このスペースは線形に割り当てられます。リージョンは、ページ割り込みが発生した場合にのみ使用できます。しかし、ページの割り込み中にページを割り当てることができない場合、mallocを呼び出すときにユーザーはだまされませんか?
2 に答える
glibc によってラップされた malloc() 呼び出しは、まず glibc によって維持されるヒープ メモリから割り当てられます。( malloc 中にカーネルで何が起こるか見てください。 ) glibc がヒープ メモリを使い果たすと、sys_brk が呼び出されてさらに割り当てられます。カーネルは、割り当てられたメモリ (ほとんどの場合、ページ フォールト ハンドラー) に最初にアクセスしたときにのみ、ユーザーの要求にメモリを割り当てます。したがって、 calloc はページを (man ページから) ゼロに初期化したため、実際に割り当てられたものを返すと思います。新しいページをフォルト ハンドラーで割り当てることができない場合は、システムのメモリが非常に少ないか、スワップが多いか、OOM に移行しようとしていることを意味します。
小さなことの 1 つは、Linux がユーザー プロセスに割り当てるときに常にメモリをスクラブすることです。これは、ページがバディ アロケータに返されるときにそうしないためです。
mallocによって割り当てられたメモリは、書き込まれる前は実メモリにはありません。一方、callocは実メモリを 1 に割り当てます。
man ページの man から:
デフォルトでは、Linux は楽観的なメモリ割り当て戦略に従います。これは、malloc() が非 NULL を返す場合、メモリが実際に使用可能であるという保証がないことを意味します。これは本当に悪いバグです。システムのメモリが不足していることが判明した場合、悪名高い OOM キラーによって 1 つまたは複数のプロセスが強制終了されます。ランダムに選択されたいくつかのプロセスを突然失うことがあまり望ましくなく、さらにカーネルのバージョンが十分に新しい環境で Linux を使用している場合、次のようなコマンドを使用してこのオーバーコミット動作をオフにすることができます:
# echo 2 > /proc/sys/vm/overcommit_memory
glibc のソースを調べたところ、calloc であると思われるものが見つかりました。
if (__builtin_expect (hook != NULL, 0)) {
sz = bytes;
mem = (*hook)(sz, RETURN_ADDRESS (0));
if(mem == 0)
return 0;
#ifdef HAVE_MEMCPY
return memset(mem, 0, sz);
#else
while(sz > 0) ((char*)mem)[--sz] = 0; /* rather inefficient */
return mem;
#endif
}