Happy My Life

日常とか技術とか

Androidのプロセスがkillされる基準

今回はAndroidLinuxカーネルな話題をひとつ。

AndroidLinuxカーネルには、メモリの空き容量が少なく(ある一定値以下に)なった場合に、プロセスを強制終了(殺す)仕組みが備わっている。

AndroidLinuxカーネルにはその機能が2つ備わっていて、一つがOOM(Out Of Memory) KillerというLinux本家での実装と、もう一つLow Memory KillerというAndroid特有の機能として実装されているものがある。

じゃあ、OOM KillerとLow Memory Killerと何が違うのか? その答がAndroid Kernel Features - eLinux.orgoom handlingに書いてあったので紹介(Thanks @androidzaurus)

OOM Killerは、シンプルな機構で空きメモリが足りなくなったらサクっとタスクを殺してしまう。そして、Low Memory Killerはそれらを、よりアクレッシブにコントロールできるようにしたもの、という説明になっている。

以下、Froyoのコードを例にしている。

プロセスをkillする基準

プロセスは、以下の基準を満した時にKillされる。まず、adjとminfreeを定義する。それらの設定は/init.rcの以下の項目で定義されている。

# Write value must be consistent with the above properties.
# Note that the driver only supports 6 slots, so we have HOME_APP at the
# same memory level as services.

    write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15
    write /sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096,5120,5632,6144

adjというのがプロセスの優先順位のようなもので、数字が小さいほど優先して実行されるプロセスという位置づけになっている。ちなみに、adjはプロセス毎に持っておりアプリケーションのライフタイムによって変化する。

minfreeとは、最低限の空きページ数を指している。1ページは4kB。1536では、1536ページ x 4KB = 6144KB という意味になる。

実際に削除されるプロセスはこれら2つの値によって決められ、基準は6段階で設定されている。

上の表だとこうなる

  • 空き容量が6144ページ(24576KB)以下で、adjが15以上のプロセスはkill
  • 空き容量が5120ページ以下で、adjが14以上のプロセスはkill
  • 空き容量が4096ページ以下で、adjが7以上のプロセスはkill
  • ...

という感じ。これらのプロセスのチェックは常に行なわれている。コードはkernel/drivers/staging/android/lowmemorykiller.cにある。

adj,minfreeの数値の由来

では、adj,minfreeの値は、どのような基準で設定されているのか。それもinit.rcの中で設定している。

# Define the oom_adj values for the classes of processes that can be
# killed by the kernel.  These are used in ActivityManagerService.
    setprop ro.FOREGROUND_APP_ADJ 0
    setprop ro.VISIBLE_APP_ADJ 1
    setprop ro.SECONDARY_SERVER_ADJ 2
    setprop ro.BACKUP_APP_ADJ 2
    setprop ro.HOME_APP_ADJ 4
    setprop ro.HIDDEN_APP_MIN_ADJ 7
    setprop ro.CONTENT_PROVIDER_ADJ 14
    setprop ro.EMPTY_APP_ADJ 15

# Define the memory thresholds at which the above process classes will
# be killed.  These numbers are in pages (4k).
    setprop ro.FOREGROUND_APP_MEM 1536
    setprop ro.VISIBLE_APP_MEM 2048
    setprop ro.SECONDARY_SERVER_MEM 4096
    setprop ro.BACKUP_APP_MEM 4096
    setprop ro.HOME_APP_MEM 4096
    setprop ro.HIDDEN_APP_MEM 5120
    setprop ro.CONTENT_PROVIDER_MEM 5632
    setprop ro.EMPTY_APP_MEM 6144

まあ、定数定義を読んでもらえば、なんとなく理解できるのではないかと。例えばFOREGROUND_APP_ADJは前面で表示されているアプリに設定されるadjの値となっている。FOREGROUND_APP_MEMは、前面で動作しているアプリの空きメモリの基準を表示している。

この設定では、前面で動作しているアプリはadj=0と設定され、空きメモリが、1536ページ以下になったら前面で動作しているアプリでもkillされる、という事が分かる。

これらの数値は、ActivityManagerServiceクラスで参照されており、FOREGROUND_APP_ADJやVISIBLE_APP_ADJの詳しい説明も、ActivityManagerServiceクラスのソースコード(frameworks/base/services/java/com/android/server/am/ActivityManagerService.java)に書かれているので、そちらを見てもらった方が早い。

また、プロセス動作中のadjの数値もActivityManagerServiceクラスのcomputeOomAdjLockedメソッドで算出している。結構長いメソッドなのでじっくり味わうとよいかも。

まあ、こんな感じでAndroidのアプリケーション(プロセス)は管理されている、らしい。ざっと調べたので、どこかに間違いがあるかもしれない。その時はコメントなどで教えてください。

AndroidSDK開発のレシピ―104個のレシピで学ぶAndroidアプリ開発の極意AndroidSDK開発のレシピ―104個のレシピで学ぶAndroidアプリ開発の極意
塚田 翔也

秀和システム 2010-08
売り上げランキング : 8440

Amazonで詳しく見る
by G-Tools