Android low memory killer 詳解

Android low memory killer 詳解

 

Android在內存管理上與linux有些小的區別。其中一個就是引入了Low memory killer .

1,引入原因

   Android是一個多任務系統,也就是說可以同時運行多個程序,這個大家應該很熟悉。一般來說,啓動運行一個程序是有一定的時間開銷的,因此爲了加快運行速度,當你退出一個程序時,Android並不會立即殺掉它,這樣下次再運行該程序時,可以很快的啓動。隨着系統中保留的程序越來越多,內存肯定會出現不足,low memory killer就是在系統內存低於某值時,清除相關的程序,保障系統保持擁有一定數量的空閒內存。

2,基本原理和重要概念

   Low memory killer根據兩個原則,進程的重要性和釋放這個進程可獲取的空閒內存數量,來決定釋放的進程。

(1)進程的重要性,由task_struct->signal_struct->oom_adj決定。

Android將程序分成以下幾類,按照重要性依次降低的順序:

名稱 oom_adj 解釋
FOREGROUD_APP 0 前臺程序,可以理解爲你正在使用的程序
VISIBLE_APP 1 用戶可見的程序
SECONDARY_SERVER 2 後臺服務,比如說QQ會在後臺運行服務
HOME_APP 4 HOME,就是主界面
HIDDEN_APP 7 被隱藏的程序
CONTENT_PROVIDER 14 內容提供者,
EMPTY_APP 15 空程序,既不提供服務,也不提供內容


其中每個程序都會有一個oom_adj值,這個值越小,程序越重要,被殺的可能性越低。

(2)進程的內存,通過get_mm_rss獲取,在相同的oom_adj下,內存大的,優先被殺。

(3)那內存低到什麼情況下,low memory killer開始幹活呢?Android提供了兩個數組,一個lowmem_adj,一個lowmem_minfree。前者存放着oom_adj的閥值,後者存放着minfree的警戒值,以page爲單位(4K)。

oom_adj 內存警戒值( 以4K爲單位)
0 1536
1 2048
2 4096
7 5120
14 5632
15 6144

3,源碼解析

    module_init(lowmem_init);
    module_exit(lowmem_exit);

    模塊加載和退出的函數,主要的功能就是register_shrinker和unregister_shrinker結構體lowmem_shrinker。主要是將函數lowmem_shrink註冊到shrinker鏈表裏,在mm_scan調用。

    下面詳細的介紹這個函數:

    for (i = 0; i < array_size; i++) {
        if (other_file < lowmem_minfree[i]) {
            min_adj = lowmem_adj[i];
            break;
        }
    }

    other_file,系統的空閒內存數,根據上面的邏輯判斷出,low memory killer需要對adj高於多少(min_adj)的進程進行分析是否釋放。

       if (nr_to_scan <= 0 || min_adj == OOM_ADJUST_MAX + 1) {
        lowmem_print(5, "lowmem_shrink %d, %x, return %d/n",
                 nr_to_scan, gfp_mask, rem);
        return rem;
    }

     判斷,系統當前的狀態是否需要進行low memory killer。

for_each_process(p) {
        struct mm_struct *mm;
        struct signal_struct *sig;
        int oom_adj;

        task_lock(p);
        mm = p->mm;
        sig = p->signal;
        if (!mm || !sig) {
            task_unlock(p);
            continue;
        }
        oom_adj = sig->oom_adj;
        if (oom_adj < min_adj) {
            task_unlock(p);
            continue;
        }
        tasksize = get_mm_rss(mm);
        task_unlock(p);
        if (tasksize <= 0)
            continue;
        if (selected) {
            if (oom_adj < selected_oom_adj)
                continue;
            if (oom_adj == selected_oom_adj &&
                tasksize <= selected_tasksize)
                continue;
        }
        selected = p;
        selected_tasksize = tasksize;
        selected_oom_adj = oom_adj;
        lowmem_print(2, "select %d (%s), adj %d, size %d, to kill/n",
                 p->pid, p->comm, oom_adj, tasksize);
    }

   對每個sig->oom_adj大於min_adj的進程,找到佔用內存最大的進程存放在selected中。

if (selected) {
        if (fatal_signal_pending(selected)) {
            pr_warning("process %d is suffering a slow death/n",
                   selected->pid);
            read_unlock(&tasklist_lock);
            return rem;
        }
        lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d/n",
                 selected->pid, selected->comm,
                 selected_oom_adj, selected_tasksize);
        force_sig(SIGKILL, selected);
        rem -= selected_tasksize;
    }

   發送SIGKILL信息,殺掉該進程。

4,配置

   通過下面兩個文件,/sys/module/lowmemorykiller/parameters/adj和/sys/module/lowmemorykiller /parameters/minfree配置系統的相關參數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章