読者です 読者をやめる 読者になる 読者になる

buddy allocator: __rmqueue_fallback()を調べる

kernel linux

前回の記事では__rmqueue_smallest()を見たので、今回は __rmqueue_fallback()を見ていきます。

この関数の呼び出し元は__rmqueue()で、__rmqueue_smallest()でメモリを確保できなかった場合に実行されます。 では、処理を見ていきましょう。

  • __rmqueue_fallback()は2つのforループにより制御されていて、ここが一番重要なところ

  • 一番外側のループは orderの最大値(通常は11かな)-1を初期値として、メモリ確保しようとしたorderまでorderを下げつつループする

  • 内側のループは配列(fallbacks)http://lxr.free-electrons.com/source/mm/page_alloc.c?v=4.0#L1032を見ていくためのもの  この配列はMIGRATEの種類を保持している2次元配列で、fallbacks[x][y]とあったときに、xはmigratetypeをインデックスに使う  例えば、migratetypeがMIGRATE_RECLAIMABLEだった場合、fallbacks[MIGRATE_RECLAIMABLE]で該当の要素を取得して、そこに設定されているMIGRATETYPEを用いてブロックを確保できるか試みる  ようは、当初指定されたmigratetypeではなくて、そのmigratetypeから変更できるマイグレートの種類からブロックの確保を行う

  • ここまでで、当たらに試すべきorderとmigratetypeが決まったので、次は実際にブロックの確保ができるかを行っていく

  • この辺の処理は前回の記事では__rmqueue_smallest()と変わらないので割愛

  • 唯一違うところは、migratetypeがMIGRATE_CMAだった場合にtry_to_steal_freepages()が呼ばれて、多少処理があります  しかし、Fedora 22Arch LinuxどちらもデフォルトではCONFIG_CMAは有効になってないので無視しましょう。  そもそも、カーネルでもmigratetypeがMIGRATE_CMAなことはまずないと考えられているみたいだし。

include/linux/mmzone.hでこうなってます。

 66 #ifdef CONFIG_CMA
 67 #  define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
 68 #else
 69 #  define is_migrate_cma(migratetype) false
 70 #endif
 71 
  • このCMAの部分以外は__rmqueue_smallest()と同じです。  ブロックを確保できて、それが元のorderよりも大きければ分割してorderが小さい方に持って行ってという流れです。

この辺が __alloc_pages_nodemask()get_page_from_freelist()を呼んでメモリを確保する部分です。 もし、get_page_from_freelist()がNULLを返した場合は、__alloc_pages_slowpath()を呼んでメモリの確保を試します。それでもメモリ確保できなければNULLを返す以外になくなります。

というわけで、次回は__alloc_pages_slowpath()を見てみましょう。

Linuxカーネル解析入門 (I・O BOOKS)

Linuxカーネル解析入門 (I・O BOOKS)