この記事はLinux Advent Calendar 2015の23日目です。
glibcのmalloc(3)とLinuxカーネルのovercommitとOOMの関連でも見てみようと思います。Linuxカーネルのシステムコールにはmalloc(3)的なものはないので、mmap(2)、brk(2)が使われます。 今回知りたかったのは、どこでovercommitを許可しているのか?というところと、どのタイミングでOOMが発生するのかという2点です。
OOM発生時の挙動についてはsatoru_takeuchiさんの覚書(2015-12-03)に詳しく書かれていますので、こちらを参照してください。 glibcのmalloc(3)に関してはがちゃぴん先生のmalloc動画を見ましょう。
今回見ているglibcのバージョンは2.22でカーネルは4.3です。
まずはmalloc(3)の大まかな処理を見ます。
malloc(3)を呼ぶとglibcの__libc_malloc()が呼ばれます。 これはmalloc/malloc.cの下のほうでaliasが設定されています。
__libc_malloc()の全容はこのようになっています。
2894 void * 2895 __libc_malloc (size_t bytes) 2896 { 2897 mstate ar_ptr; 2898 void *victim; 2899 2900 void *(*hook) (size_t, const void *) 2901 = atomic_forced_read (__malloc_hook); 2902 if (__builtin_expect (hook != NULL, 0)) 2903 return (*hook)(bytes, RETURN_ADDRESS (0)); 2904 2905 arena_get (ar_ptr, bytes); 2906 2907 victim = _int_malloc (ar_ptr, bytes); 2908 /* Retry with another arena only if we were able to find a usable arena 2909 before. */ 2910 if (!victim && ar_ptr != NULL) 2911 { 2912 LIBC_PROBE (memory_malloc_retry, 1, bytes); 2913 ar_ptr = arena_get_retry (ar_ptr, bytes); 2914 victim = _int_malloc (ar_ptr, bytes); 2915 } 2916 2917 if (ar_ptr != NULL) 2918 (void) mutex_unlock (&ar_ptr->mutex); 2919 2920 assert (!victim || chunk_is_mmapped (mem2chunk (victim)) || 2921 ar_ptr == arena_for_chunk (mem2chunk (victim))); 2922 return victim; 2923 } 2924 libc_hidden_def (__libc_malloc)
単純に言うと、_int_malloc()で要求されたメモリが確保できればOK。できなかったら、arena_get_retry()でarenaを変えてからもう一度チャレンジというのがmalloc(3)の大雑把な挙動になってます。
_int_malloc()はそれなりに長い関数なのでさくっと流したいところです。
3311 static void * 3312 _int_malloc (mstate av, size_t bytes) ~~~ 3345 /* There are no usable arenas. Fall back to sysmalloc to get a chunk from 3346 mmap. */ 3347 if (__glibc_unlikely (av == NULL)) 3348 { 3349 void *p = sysmalloc (nb, av); 3350 if (p != NULL) 3351 alloc_perturb (p, bytes); 3352 return p; 3353 }
__libc_malloc()でarena_get()を呼んで取得したarenaがNULLということは、使用可能なarenaが無いということで、sysmalloc()というのが呼ばれます。
また、_int_malloc()の最後のほうでもarenaからではなく、OS側にメモリを要求する必要があるときにsysmalloc()を呼んでいます。
3816 /* 3817 Otherwise, relay to handle system-dependent cases 3818 */ 3819 else 3820 { 3821 void *p = sysmalloc (nb, av); 3822 if (p != NULL) 3823 alloc_perturb (p, bytes); 3824 return p; 3825 }
では、sysmalloc()をさくっと見ていきます。
2260 static void * 2261 sysmalloc (INTERNAL_SIZE_T nb, mstate av) 2262 {
基本的にmmap(2)もしくはsbrk(2)を使うという感じです。 OSがmmapをサポートしていて、要求されたサイズがmmapで確保する場合のしきい値を超えてないなんて場合にmmap(2)でメモリの確保をしにいきます。
2286 /* 2287 If have mmap, and the request size meets the mmap threshold, and 2288 the system supports mmap, and there are few enough currently 2289 allocated mmapped regions, try to directly map this request 2290 rather than expanding top. 2291 */ 2292
mmap(2)に失敗し、使用可能なarenaも無ければ終了です。
2368 /* There are no usable arenas and mmap also failed. */ 2369 if (av == NULL) 2370 return 0;
次にメモリを確保しようとしたarenaの種別によって処理が変わっています。
2394 if (av != &main_arena) 2395 { ~~~ 2445 else /* av == main_arena */
まず、av != &main_arenaの場合。heapを拡張する(grow_heap())、heapを新しく作る(new_heap())、mmapするのどれかになります。
2402 if ((long) (MINSIZE + nb - old_size) > 0 2403 && grow_heap (old_heap, MINSIZE + nb - old_size) == 0) ~~~ 2410 else if ((heap = new_heap (nb + (MINSIZE + sizeof (*heap)), mp_.top_pad))) ~~~ 2441 else if (!tried_mmap) 2442 /* We can at least try to use to mmap memory. */ 2443 goto try_mmap
main_arenaの場合は、sbrk(2)でデータセグメントを拡張し、
2476 if (size > 0) 2477 { 2478 brk = (char *) (MORECORE (size)); 2479 LIBC_PROBE (memory_sbrk_more, 2, brk, size); 2480 }
これに失敗したらmmapを試します。
/* Don't try if size wraps around 0 */ 2509 if ((unsigned long) (size) > (unsigned long) (nb)) 2510 { 2511 char *mbrk = (char *) (MMAP (0, size, PROT_READ | PROT_WRITE, 0)); 2512
大雑把に見ていくとsysmalloc()はだいたいこのような流れです。
このほかarenaを作るというときもあって、これは_int_new_arena()で行います。メモリを確保する処理はnew_heap()ですね。
722 /* Create a new arena with initial size "size". */ 723 724 static mstate 725 _int_new_arena (size_t size) 726 { 727 mstate a; 728 heap_info *h; 729 char *ptr; 730 unsigned long misalign; 731 732 h = new_heap (size + (sizeof (*h) + sizeof (*a) + MALLOC_ALIGNMENT), 733 mp_.top_pad);
new_heap()はmmap(2)を使います。
どんなときにarenaを作っているかというと例えば、arena_get_retry()でメモリを確保しようとしたarenaがmain_arenaではない場合、arena_get2()を呼んで、どこも空いてなければなんて時です。
887 if (__glibc_unlikely (n <= narenas_limit - 1)) 888 { 889 if (catomic_compare_and_exchange_bool_acq (&narenas, n + 1, n)) 890 goto repeat; 891 a = _int_new_arena (size); 892 if (__glibc_unlikely (a == NULL)) 893 catomic_decrement (&narenas); 894 } 895 else 896 a = reused_arena (avoid_arena);
ここまでがglibcの処理でした。ではカーネル側を見てきましょう。
まずは、overcommitの設定を見ている関数ですが、これは__vm_enough_memory()です。 vm.overcommit_memory(/proc/sys/vm/overcommit_memory)の値を見てovercommit可能なら0を、できないようなら-ENOMEMを返します。overcommitができない場合というのは、設定で許可していない場合とovercommit可能かどうか計算した結果だめだった場合の2パターンです。 __vm_enough_memory()は直接使用されていなくて、security_vm_enough_memory_mm()という関数から呼ばれます。
security_vm_enough_memory_mm()を呼んでいる箇所はいくつかあります。glibcのmalloc(3)がbrk(2)、mmap(2)を使っているのでその辺りをチェックするとやはり読んでいます。
do_brk()ではこのように使っています。
2766 if (security_vm_enough_memory_mm(mm, len >> PAGE_SHIFT)) 2767 return -ENOMEM;
mmapの場合はmmap_region()にて使用しています。
1572 /* 1573 * Private writable mapping: check memory availability 1574 */ 1575 if (accountable_mapping(file, vm_flags)) { 1576 charged = len >> PAGE_SHIFT; 1577 if (security_vm_enough_memory_mm(mm, charged)) 1578 return -ENOMEM; 1579 vm_flags |= VM_ACCOUNT; 1580 }
mmap_region()はdo_mmap()の最後のほうで呼んでいます。mmap_region()の返り値がmmap(2)の返り値ですね。
1402 addr = mmap_region(file, addr, len, vm_flags, pgoff); 1403 if (!IS_ERR_VALUE(addr) && 1404 ((vm_flags & VM_LOCKED) || 1405 (flags & (MAP_POPULATE | MAP_NONBLOCK)) == MAP_POPULATE)) 1406 *populate = len; 1407 return addr;
というわけで、brk(2)、mmap(2)ともにsecurity_vm_enough_memory_mm()を呼んで、overcommit可能か調べて可能ならメモリを確保します。
do_brk()の場合はこのようになってます。すでに使える領域があればそれを、なければvma構造体を新規に作ります。mmap_region()も同じ感じです。
2769 /* Can we just expand an old private anonymous mapping? */ 2770 vma = vma_merge(mm, prev, addr, addr + len, flags, 2771 NULL, NULL, pgoff, NULL, NULL_VM_UFFD_CTX); 2772 if (vma) 2773 goto out; 2774 2775 /* 2776 * create a vma struct for an anonymous mapping 2777 */ 2778 vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); 2779 if (!vma) { 2780 vm_unacct_memory(len >> PAGE_SHIFT); 2781 return -ENOMEM; 2782 } ~~~ 2785 vma->vm_mm = mm; 2786 vma->vm_start = addr; 2787 vma->vm_end = addr + len; 2788 vma->vm_pgoff = pgoff; 2789 vma->vm_flags = flags; 2790 vma->vm_page_prot = vm_get_page_prot(flags); 2791 vma_link(mm, vma, prev, rb_link, rb_parent);
最後にメモリが足りなくなった時の処理を。 メモリが足りなくなった場合の最終的な処理はcheck_panic_on_oom()でpanicするか、check_panic_on_oom()を呼んだ側でプロセスをkillするかです。 check_panic_on_oom()これを呼んでいるところは2箇所あります。
1つはout_of_memory()。
675 constraint = constrained_alloc(oc, &totalpages); 676 if (constraint != CONSTRAINT_MEMORY_POLICY) 677 oc->nodemask = NULL; 678 check_panic_on_oom(oc, constraint, NULL);
もうひとつはmem_cgroup_out_of_memory()。
1332 if (fatal_signal_pending(current) || task_will_free_mem(current)) { 1333 mark_oom_victim(current); 1334 goto unlock; 1335 } 1336 1337 check_panic_on_oom(&oc, CONSTRAINT_MEMCG, memcg); 1338 totalpages = mem_cgroup_get_limit(memcg) ? : 1;
out_of_memory()を呼ぶ流れとしては、下記の流れが基本っぽいです。
__alloc_pages_nodemask() -> __alloc_pages_slowpath() -> __alloc_pages_may_oom() -> out_of_memory()
これはpageを確保しようとして失敗したケース。
次にmem_cgroup_out_of_memory()が呼ばれる流れはこうです。do_page_fault()と__do_page_fault()はアーキテクチャ依存の関数です。
do_page_fault() -> __do_page_fault() -> mm_fault_error() -> pagefault_out_of_memory() -> mem_cgroup_oom_synchronize() -> mem_cgroup_out_of_memory()
まず、__alloc_pages_nodemask()でOOMが発生するパターンですが、これは例えば、kmem_cache_zalloc()を呼んだ時に空いているslabオブジェクトがなかったので、slabを作るためにpageの新規確保をしに行ったけど(slowpath)pageすら確保できなくてOOMというパターンでしょうか。
ページフォルトの場合はpageの割りあてが必要だったけど、できなかったケースですね。pagefault_out_of_memory()に説明が書かれています。
707 /* 708 * The pagefault handler calls here because it is out of memory, so kill a 709 * memory-hogging task. If any populated zone has ZONE_OOM_LOCKED set, a 710 * parallel oom killing is already in progress so do nothing. 711 */ 712 void pagefault_out_of_memory(void)
というわけで、malloc(3)とovercommitの許可、OOMの発生なんかを見てきました( ´ー`)フゥー...
APIデザインケーススタディ ~Rubyの実例から学ぶ。問題に即したデザインと普遍の考え方 (WEB+DB PRESS plus)
- 作者: 田中哲
- 出版社/メーカー: 技術評論社
- 発売日: 2015/12/16
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る