1、Linux中的進程管理
在Linux中,進程是指處理器上執行的一個實例,可以使用任意資源以便完成它的任務,具體的進程管理,是經過「進程描述符」來完成的,對應Linux內核中的task_struct數據結構。進程描述符,包括進程標識、進程的屬性、構建進程的資源。
一個進程能夠經過fork()或者vfork()調用建立出子進程,這些子進程能夠訪問父進程的地址空間,包括文本段、數據段、堆棧段。java
一般狀況下,調用fork()的進程處於task_running狀態,則fork出來的子進程默認也處於task_running狀態,具體來講,在fork以後、exec以前,子進程處於task_running狀態中的就緒狀態。linux
進程的運行狀態包括如下幾種。
一、task_running:可執行狀態。包含正在CPU上執行的、可執行可是還沒有被調度執行這兩種子狀態,後者對應就緒狀態。
二、task_interruptible:可中斷的睡眠狀態。由於等待某事件的發生而被掛起。當等待的事件發生時,處於該狀態的進程將被喚醒。
三、task_uninterruptible:不可中斷的睡眠狀態。處於睡眠狀態,可是此刻進程是不可中斷的。此時進程不響應異步信號,不能經過發送信號的方式kill之,但能夠響應硬件中斷,例如磁盤IO,網絡IO等。
四、task_stopped / task_traced:暫停狀態或跟蹤狀態。處於task_traced狀態的進程不能響應SIGCONT信號而被喚醒,只能等到調試進程經過ptrace系統調用執行ptrace_cont、ptrace_detach等操做,或調試進程退出,被調試的進程才能恢復task_running狀態。
五、task_zombie :殭屍狀態。在進程收到SIGSTOP、SIGTTIN、SIGTTOU等信號,即將終止時,會進入該狀態,此時進程成爲殭屍進程。該狀態的進程會處理一些資源釋放工做,而後發送SIG_CHLD信號給父進程。android
2、Android進程管理機制
在linux系統中,應用程序執行完成後,最終會清理一些進程使用的文件描述符、釋放掉進程用戶態使用的相關的物理內存,清理頁表,而後發送信號給父進程。但在Android系統中,應用程序執行完成後,該應用所在的進程一般仍是會在後臺繼續運行,除非應用程序在執行完成後主動調用System.exit或者Process.killProcess之類的方法。
這樣設計的好處,主要是加快應用程序再次啓動的速度,改善用戶體驗。當內存不足時,系統會按照特定規則,包括進程優先級、佔用內存等信息,來清理進程並釋放對應的資源。git
一、進程優先級
在Android中,進程按優先級能夠分爲:前臺進程、可見進程、服務進程、後臺進程、空進程。優先級依次下降。github
1)Forground,前臺進程
這種進程優先級最高,能夠細分下面幾種狀況:
case1:有個前臺Activity,特指已經執行了onResume但還沒執行onPause的Activity;
case2:有個Service且和一個前臺Activity綁定的進程;
case3:調用了startForground的前臺Service所在進程(這種服務會帶個通知);
case4:正在執行onReceive函數的BroadcastReceiver所在進程,以及正在執行服務的生命週期方法諸如onCreate、onStartCommand的進程。緩存
2)Visible,可見進程
可見進程沒有處於前臺的組件,可是用戶仍然能看到進程中的組件,例如某進程的Activity調用了申請權限對話框,具體包括:
case1:有個僅onPause被調用的Activity(可見但被遮擋);
case2:進程中有個Service且和一個可見Activity綁定。
注意這裏的可見Activity不包括前臺Activity(不然就是前臺進程了),而且這種進程在內存不足時也是可能被殺掉的。性能優化
3)Service,服務進程
服務進程是指有個經過startService方式啓動的Service進程,而且不屬於前面兩類進程,例如MediaScannerService。網絡
4)Background,後臺進程
當前不可見的Activity所在進程屬於後臺進程,即它們的onStop被調用過,例如用戶按下home鍵。
對於後臺進程,系統會保存這些進程到一個LRU列表,當系統須要回收內存時,LRU中那些最近最少使用的進程將被殺死。數據結構
5)Empty,空進程
空進程不包含任何組件,當系統從新須要它們時(例如用戶在別的進程中經過startActivity啓動了它們),能夠省去fork進程、建立Android運行環境等漫長的工做,節省時間,緩存性質。這種進程優先級最低,在任什麼時候候均可能被殺掉。異步
如前所述,大部分應用是單進程的,可是進程和組件類型是高度關聯的。若是應用中有生命週期差別較大的組件,考慮使用多進程分別處理。一方面是讓佔用資源較多的進程能夠被系統及時回收,另外一方面,避免那些須要長時間持續運行的任務因爲組件生命週期的影響進入後臺進程執行。
二、內存不足時的殺進程策略
在Linux系統中,進程的優先級對應一個參數,也就是oom_score_adj,lowmemorykiller程序會根據內存使用狀況和進程優先級,動態殺進程以釋放內存資源。
當內存不足或者發生oom錯誤時,lowmemorykiller根據特定策略先殺優先級最低的進程,而後逐步殺優先級更低的進程(一樣優先級會按照內存佔用狀況排序),依此類推,以回收預期的可用系統資源,從而保證系統正常運轉。
在Android系統中,進程的組件狀態變化時,組件所在進程的優先級也會發生變化。一個典型的場景是,切換到後臺的進程,其優先級低於前臺進程。
App的前臺/後臺切換操做對oom_score_adj的影響,咱們可使用adb命令cat/proc/[pid]/oom_score_adj來查看。詳細的優先級信息在ProcessList.java中有定義,對應的部分進程類型以下。
內存不足時,AMS會根據上述動態優先級信息,經過ProcessRecord,在native層給指定進程發送信號以終止進程,進而釋放內存資源。相關函數包括:killProcessesBelowForeground, killProcessesBelowAdj, ProcessRecord.kill, killPids等。
(相關完整且成體系的文章,可參見本人原創的開源電子書《Android系統與性能優化》,地址:https://github.com/carylake/androidnotes)