Android Linuxのプロセスメモリ管理 その2

今、私たちはメモリ領域や、空き領域を知っています。
実機があれば adb shell ps と打ってみましょう。

私のHTC Desire HDの結果はこんな感じです。

VSSとRSSの列が見えるはずです。  
VSS(henceforth VSS)はプロセスが必要とするメモリの量です。  
RSS(Resident Set Size)は物理メモリに位置する本当に存在するメモリの量です。  
(メモリ確保の要求がされたもの)。
上記のようにVSSとRSSの違いの主な理由はデマンドページングです。
では、全てのRSSサイズを足してみましょう。
面白いことにmeminfoの総メモリ・サイズよりも大きいはずです。

例えば、Androidでリンク前のオブジェクトがあったとします。
オブジェクトはプロセスで共有されています。
そしてRSSサイズはそのオブジェクトのサイズもまた含みます。
そういうわけでRSSの総サイズはメモリ・サイズより大きいのです。

より深くRSSについて知るために、以下の例を見てみましょう。
空のプログラムを作り、実行してそれのVSSを確認してください。
例えば以下のようなプログラムです。

void main() { 
    sleep(1000);
}

・・・これのプログラムサイズが1M!
カーネルはプロセスハンドルそのものでメモリを確保します。
例えばページ・テーブル、例えば制御ブロックなどです。

通常の32bitアプリケーションではページ・テーブルで4KBページ単位と4GBページの仮想メモリを使用します。
だからメモリのページ数は 4GB / 4KB で 1MBとなります。
1MBのページを追跡するためには確かに、ある程度必要となるでしょう。
そう少なくとも実際小さくはありません。
メモリ量が少ないプロセスにすら必要とされます。

先に書いたようにRSSは共有メモリを含みます。
しかし、私たちはメモリの本当のサイズが知りたいのです。

そこでPSS(Proportional Set Size)というものが存在します。
共有されていないprivateメモリ + 共有されてるメモリ ÷ 共有しているプロセス=PSSです。
PSSは本当のメモリサイズとなります。

ではどうしたら確認できるでしょう。
一番簡単な方法は以下のコマンドを打ってみましょう。

/proc/<PID>/smaps

これでPSSを簡単に知ることが出来ます。
詳細についてはカーネルソースの task_mmu.c で確認できます。