[Android]你不知道的Android进程化(3)--进程等级
我們可以看到現在Android的運行內存越來越大,6G、8G的大內存時代,越大運存將允許運行越多的app,而Android系統也組建增大進程可以申請的最大運存量。Android 系統將盡量長時間地保持應用進程,內存是有限的,為了新建進程或運行更重要的進程,最終需要移除舊進程來回收內存。
為了確定哪些進程是能夠被移除的,Android系統引用了進程優先級別的機制。Android進程的優先層級結構一共分5層。
1.前臺進程:(foreground process)
用戶當前操作所必需的進程。如果一個進程滿足以下任一條件,即視為前臺進程:
(1)用戶正在交互使用的 Activity(已調用 Activity 的 onResume() 方法)
(2)某個 Service,后者綁定到用戶正在交互的 Activity。
(3)正在“前臺”運行的 Service(服務已調用 startForeground())
(4)正執行一個生命周期回調的 Service(onCreate()、onStart() 或 onDestroy())
(5)正執行其 onReceive() 方法的 BroadcastReceiver
通常,在任意給定時間前臺進程都為數不多。只有在內存不足以支持它們同時繼續運行這一萬不得已的情況下,系統才會終止它們。 此時,設備往往已達到內存分頁狀態,因此需要終止一些前臺進程來確保用戶界面正常響應。
2.可見進程:
沒有任何前臺組件、但仍會影響用戶在屏幕上所見內容的進程。 如果一個進程滿足以下任一條件,即視為可見進程:
(1)不在前臺、但仍對用戶可見的 Activity(已調用其 onPause() 方法)。例如,如果前臺 Activity 啟動了一個對話框,允許在其后顯示上一 Activity,則有可能會發生這種情況。
(2)綁定到可見(或前臺)Activity 的 Service。 (不包含startForground()的情況)
可見進程被視為是極其重要的進程,除非為了維持所有前臺進程同時運行而必須終止,否則系統不會終止這些進程。
3.服務進程
正在運行已使用 startService() 方法啟動的服務且不屬于上述兩個更高類別進程的進程。盡管服務進程與用戶所見內容沒有直接關聯,但是它們通常在執行一些用戶關心的操作(例如,在后臺播放音樂或從網絡下載數據)。因此,除非內存不足以維持所有前臺進程和可見進程同時運行,否則系統會讓服務進程保持運行狀態。
4.后臺進程:
包含目前對用戶不可見的 Activity 的進程(已調用 Activity 的 onStop() 方法)。這些進程對用戶體驗沒有直接影響,系統可能隨時終止它們,以回收內存供前臺進程、可見進程或服務進程使用。 通常會有很多后臺進程在運行,因此它們會保存在 LRU (最近最少使用)列表中,以確保包含用戶最近查看的 Activity 的進程最后一個被終止。如果某個 Activity 正確實現了生命周期方法,并保存了其當前狀態,則終止其進程不會對用戶體驗產生明顯影響,因為當用戶導航回該 Activity 時,Activity 會恢復其所有可見狀態。 有關保存和恢復狀態的信息,請參閱 Activity文檔。
5.空進程
不含任何活動應用組件的進程。保留這種進程的的唯一目的是用作緩存,以縮短下次在其中運行組件所需的啟動時間。 為使總體系統資源在進程緩存和底層內核緩存之間保持平衡,系統往往會終止這些進程。
根據進程中當前活動組件的重要程度,Android 會將進程評定為它可能達到的最高級別。例如,如果某進程托管著服務和可見 Activity,則會將此進程評定為可見進程,而不是服務進程。
連接adb命令,使用dumpsys meminfo命令時,會列出當前系統的所有進程,不同進程放入不同的分類。
Linux API:
Linux提供了兩個API用于設置調度優先級及調度策略。
其中,which和who聯合使用。
當which為PRIO_PROGRESS時,who代表一個進程,即pid;
當which為PRIO_PGROUP時,who代表一個進程組,即gid;
當which為PRIO_USER時,who代表一個用戶,即uid。
prio用于設置進程的nice值,取值范圍為-20~+19。
該值越大表示進程越友好(nice),即對CPU資源的依賴越低。
于是,進程的prio值越大,其被調用的優先級越低。
其中,pid表示進程id。
policy表示調度策略。
Linux定義了很多種調度策略,具體的內容可以參考相關的資料。
param參數中,最重要的是該結構體中的sched_priority變量。
該變量用于設置該調度策略下,進程的優先級。
以上只是簡單的進程級別分類,如果按照lowmeorykiller中進程的分類將會更為完整一點。
每一類別的進程會有其oom_adj值的取值范圍,oom_adj值越高則代表進程越不重要,在系統執行低內存殺進程操作時,會從oom_adj值越高的開始殺。
ProcessList中記錄了進程的等級判斷
系統級別的進程都是使用負數的進程級別,所以不會被判定回收
系統級別進程
oom_adj是每進程的進程級別。
如何查看某個應用的oom_adj數值?
首先adb shell#ps查看應用的PID。
然后#cat /proc/PID/oom_adj的結果就是。
此源碼是android 7.1.1源碼,可能舊的源碼等級數字會小一點。
前臺進程 oom_adj 0
可見進程 oom_adj 100
可感知進程 oom_adj 200
后臺進程 oom_adj 300
后臺重量級進程 oom_adj 400
服務進程 oom_adj 500
Home進程 oom_adj 600
前一個進程 oom_adj 700
服務進程 oom_adj 800
緩存進程 oom_adj 900~906
其職能和舊版本的Android并沒不同,可以借鑒# 溪亭瀝酒的下圖
當需要釋放內存,運行新的app的時候,進程oom_adj數值越高,進程就越容易被lowmemroykiller殺死回收。
在ActivityManager當中又自有一套進程分級,而且更加詳細的級別,和ProcessList中的某些等級是對應的,可以從ProcessList中看出。(圖中等級并不是全部等級)
AMS內部就是使用這份進程等級記錄。
內存管理進程是以一種類似Lru模型來做的。
了解進程等級,對以后進程保活,進程調度有更加深刻的認識。
剛開始都是說一些比較基礎的進程知識,之后會有更加深入的章節,介紹進程管理的相關源碼。
本節就到這里。
作者:CangWang
鏈接:https://www.jianshu.com/p/a525932db11c
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
總結
以上是生活随笔為你收集整理的[Android]你不知道的Android进程化(3)--进程等级的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: replugin源码解析之replugi
- 下一篇: [Android]你不知道的Androi