android進程的優先順序
① Android 進程管理篇(四)-cpu限制
梳理Process進程相關知識點,再繼續補充點內容。
linux系統中對進程的管理無非是從調度策略、優先順序以及CPU限制三個角度進行配置與管理,那麼Android中主要是通過AMS來管理應用程序進程的,是不是也是從這三個方面進行管理的呢?答案是肯定的,那麼本篇文章先來看看cpuset負載均衡在AMS中是如何應用的。
cpuset是Linux cgroup子系統,它為cgroup任務分配單獨的CPU和內存。單獨分配CPU即表明進程可調度cpu范圍。cpu按不同的晶元,大小核數目和頻率都有差別,大核頻率高處理速度相對比小核快,而Android系統實際上還是響應優先於吞吐的交互型系統,因此Android AMS對進程管理於不同優先順序的進程在調度cpu限制上會做有一些策略,以保證更好的交互響應。
還是回到AMS中與adj相關的有三個方法,這三個方法值得看一萬遍,每一遍都會有新收獲:
聚焦到computeOomAdjLocked方法,該方法主要是根據進程的四大組件狀態決定當前進程的adj優先順序。
以TOP_APP為例,這里ProcessRecord 的curSchedGroup屬性對應的是cup調度組,而在後續applyOomAdjLocked中會執行Process的setProcessGroup方法。
調用Process的setProcessGroup方法
setProcessGroup是個native方法,並且這里分了若干類型的group,這里看top app優先順序是最高的。接著jni到native
這里直接調用sched_policy.cpp的set_cpuset_policy,並傳入對應的pid和SchedPolicy
這里主要就是通過policy對應具體的fd句柄,然後通過add_tid_to_cgroup()寫cpuset對應節點。這里要注意,如果cpusets_enabled為false的話,會走set_sched_policy,這部分下篇會講到。
看看對應的fd是什麼:
那我們來看看對應節點是什麼內容:
然後看看對應的cpuset配置:
顯然,top app 滿核隨便跑,foreground跑在除了3這個核以外的所有核上, 而background只能跑在小核上。
不同晶元平台配置會有差別。
② Android線程優先順序和進程oom_adj
在處理app啟動速度的時候,可以設置主線程的優先順序,保證主線程佔用的cpu足夠久。進程的oom_adj,決定了當內存不夠的時候,lmk會根據oom_adj的大小依次釋放內存。
android中對線程等級劃分如下:
設置線程的優先順序分為:android 提供的api和java sdk自帶的api
注意: 要使用android提供的api設置,用java提供的作用不夠顯著
作用: 可以在主線程設置主線層等級;在Glide載入圖片的時候設置低優先順序。當圖片量很大的時候可以降低載入圖片線程的等級
android內存不夠了,會觸發oom機制,lowMemoryKiller會根據每個進程的oom_adj的等級,依次殺死進程,釋放內存。
lom會根據free的內存的值,來判斷kill掉哪個等級下的進程。例如當空閑內存只有64M了。會kill掉oom_adj 為12-15的進程
真實案例:應用A跳到第三方應用B,在第三方應用B中播放視頻,載入大量圖片,導致返回的時候,應用A走了SplashActivity。通過logcat發現A應用被kill掉了
③ Android 進程管理篇(五)-調度策略與優先順序
接上篇cpuset,這篇來看看進程優先順序與調度策略管理。
Linux中,優先順序號一共有0-139,其中0-99的是RT(實時)進程,100-139的是非實時進程。
數字越低優先順序越高。
SCHED_IDLE idle狀態低優先順序進程調度
先看Process中調度策略的劃分,與上面介紹的一樣。
首先在AMS中封裝了FIFO和NORMAL的兩個策略,NORMAL好說,看看FIFO在哪用到
這里Process.setThreadScheler並沒有太多的應用,我們直接來看優先順序設置吧。else中將top app的UI線程與render線程都設置為TOP_APP_PRIORITY_BOOST優先順序,nice值為-10,非常高。
這里主要調用androidSetThreadPriority方法
這里通過set_sched_policy來調整調度策略,並通過setpriority設置進程優先順序。這里不特意區分進程與線程了,反正在linux中都是進程。
這里與前面的cpuset非常相似,依然是寫節點,節點前面也提了就是:
那麼這里又引入了一個schedtune子系統,簡單介紹下:
schedtune是ARM/Linaro為了EAS新增的一個子系統,主要用來控制進程調度選擇CPU以及boost觸發。通過權重來分配CPU負載能力來實現快速運行。高權重意味著會享受到更好的cpu負載來處理對應的任務,換句話說你能享受相對更好的cpu運行性能。
簡單梳理下schedtune和不同類型SchedPolicy之間的對應關系:
看下具體文件夾內容:
系統配置:
這里/dev/stune相關配置只做了這么一個
④ Android保活方案
系統出於性能和體驗上的考慮,APP退到後台後並不會真正的kill、掉進程,而是將其緩存起來。
打開的應用越多,緩存的應用也就越多,在系統進程不足的情況下,系統根據自己的一套進程回收機制,來判斷kill掉哪些進程,以騰出進程給需要的app,這套進程回收機制叫做low memory killer。
內存閥值,每個手機都不一樣,當可用內存小於該值得時候,Android就會殺死對應優先順序得進程。
進程的優先順序通過oom_adj來判斷,oom_adj取值如下:
0-3是比較安全的oom_adj一般不會被系統殺死的,所以我們只要保證自己的app oom_adj在0-3之間就可以了。
可以通過adb命令:cat /proc /4181/oom_adj來查看自己app的oom_adj的值
4181是進程號
原理:手機關閉屏幕的時候,偷偷創建一個activity,讓應用成為前台進程,打開屏幕時關閉activity,這樣用戶就不會發現什麼異常,我們知道前台應用的oom_adj為0是不會被殺死的,這樣就達到看保活的目的。
缺點:activity不夠干凈,只有在息屏的時候才生效,存在局限性比較大,而且谷歌原生的系統息屏的時候不會清理進程,但是現在很多廠商會在息屏的時候清理內存,所以本方案的可行性不高,可以作為了解。
保活原理:啟動一個前台服務,從而拉高整個應用的優先順序。
因為一旦通知被用戶幹掉那麼該保活方案就不好用了,所以通知圖標存在與否是該方案是否可行的關鍵。
但是該方案是谷歌官方承認的保活方案,所以可行性還是很高的。
需要適配
API<18通知圖標不會顯示
API>=18&&API<26可以啟動雙服務,綁定同樣的D,然後stop
這個方法的原理是8.0系統之前會根據服務的id來判斷通知,那麼第二個id設置跟第一個相同,然後自殺,系統就會誤認為此通知已死就不會通知了,那麼通知欄上面就不會顯示
API>=26後暫時沒有方式能夠隱藏
8.0之後不可以創建同樣的id的通知,所以此隱藏通知的方法就不好用了,當然了,通知顯示與否不是該方案成功的評判標准,所以說還是可以用的。
在發生特定系統事件時,系統會發出廣播,通過在 Androidmanifest中靜
態注冊對應的廣播監聽器,即可在發生響應事件時拉活
但是從 android7.0開始,對廣播進行了限制,而且在8.0更加嚴格該方法就不適用了。
有多個app在用戶設備上安裝,只要開啟其中一個就可以將其他的app也拉
活。比如手機里裝了手Q、QQ空間、興趣部落等等,那麼打開任意一個app後,其
他的app也都會被喚醒
系統每隔一段時間會進行賬戶同步,當系統去賬戶同步的時候(不一定多長時間,跟系統有關),我們就去拉活app,這個方案是非常穩定的,當然了國內的系統都是定製的,所以還是需要一定的適配的。
優點:系統喚醒,比較穩定
缺點:時間不能把控
JobScheler允許在特定狀態與特定時間間隔周期執行任務。可以利
用它的這個特點完成保活的功能,效果即開啟一個定時器,與普通定時器不
同的是其調度由系統完成。
同樣在某些ROM可能並不能達到需要的效果
⑤ Android提升服務進程優先順序
在android應用開發時,我們經常會在後台開一個service,來處理一些業務操作。最近公司的一個項目就是,通過service不斷地和硬體設備交互,獲取數據,在頁面長時間停留在一個頁面時,手機的屏幕會出項鎖屏的狀況,這時,我們的應用的優先順序就會下降,很多次,等打開屏幕的瞬間,我發現原來的原來的進程被殺死了,應用又回到了首頁,尤其是在Android高版本的系統中尤為突出。所以下面我們通過提成優先順序的方式,來進行進程保活
2.在程序開始的地方注冊這個廣播接收者
4.定義這個activity的style屬性 value - style.xml 文件
5.Androidmanifest文件中注冊這個activity
大功告成!
經過測試,本人的華為榮耀9i,原來存在的問題被解決了,希望大家能互相交流經驗。
⑥ 進程保活
一 、問:什麼是進程保活?
答:進程保活就是進程永遠存在內存中,是殺不死的,就算殺死了也會有辦法重新啟動起來,其實這些並不是流氓手段,很多情況下,如果你想給你的用戶提供服務,就必須有一個進程常駐著,便於在特定的時候做一些特定的事情,比如廣播接受者,他就不支持靜態注冊,也就是說如果我們想接受屏幕開關啟動的廣播,必須要在進程中動態注冊,這個時候如果沒有一個常駐的進程,鎖屏業務就無法正常的為用戶展開服務。
二、問:進程是怎麼死掉的呢?
答:其實進程被殺死的原因,一方面是人為的,二、可能被第三方應用殺死,如殺敵軟體等。
三、問:Android進程的優先順序?
答:
1、前台進程 (Foreground process):用戶當前操作所在的進程,當內存不足以承擔前台進程的使用,才有可能回收
2、可見進程(Visible process):沒有任何前台組件,但是仍然會影響屏幕上所見內容,他是一種極為重要的進程,除非為了維持前台進程,因內存不足,有可能會回收掉可見進程,否則系統是不會回收可見進程。
3、服務進程(Service process):他與用戶所見的內容是沒有直接關聯,但是他們通常執行一些用戶關心的操作,比如說在後台獲取網路數據,後台播放音樂,後台進行一些數據計算等。被殺死的原因:也是為了
支持前台進程和可見進程,因內存不足情況下才會被回收。
4、後台進程(BaclGround process):對用戶的體驗沒有直接的影響,用戶可以隨時終止他們,這個進程是為了供給上面三個進程來使用的,通常在後台進程運行著很多操作,他們保存在一個列表當中,為了確保用戶最近查看Activit的進程最後一個被終止,他是一個LRU演算法,
5、空進程(Empty process) :保存這個進程的唯一目的就是用來做緩存,以縮短下次在運行組件所需的啟動時間,為了使系統總體的資源在進程緩存和內存底層之間保持平衡。它是不包括任何組件的進程.
四、問:Android進程的回收策略?
答:Android進程的回收策略主要是通過Low memory killer機制來完成的。
Low memory killer:通過一些比較復雜的評分機制,對進程進行打分,然後講分數的進程判定為bad進程,殺死並釋放內存。Low memory killer是定時進行檢查的,它主要是通過進程的OOM_ODJ來判斷進程的優先順序。當OOM_ODJ的值越小,進程的優先順序越高,而OOM_ODJ越不會去回收。反之就會被回收。
注意:Low memory killer和out memory不一樣的地方:out memory機制只有當系統內存不足的時候才會啟動檢查,而Low memory killer是定時進行檢查的,它主要是通過進程的OOM_ODJ來判斷進程的優先順序。
五、問:進程保活方案?
答:Android進程的回收策略主要是通過Low memory killer機制來完成的。
1、利用系統廣播拉活,在發生系統事件的時候,系統會發出相應的廣播,
詳情查看:http://blog.csdn.NET/sunshinetan/article/details/53126857
2、利用系統Service機制拉活,在Service有一個onStartCommand
推薦博客:http://blog.csdn.net/wulianghuan/article/details/8596467
Android開發的過程中,每次調用startService(Intent)的時候,都會調用該Service對象的onStartCommand(Intent,int,int)方法,然後在onStartCommand方法中做一些處理。然後我們注意到這個函數有一個int的返回值,這篇文章就是簡單地講講int返回值的作用。從Android官方文檔中,我們知道onStartCommand有4種返回值:
START_STICKY:如果service進程被kill掉,保留service的狀態為開始狀態,但不保留遞送的intent對象。隨後系統會嘗試重新創建service,由於服務狀態為開始狀態,所以創建服務後一定會調用onStartCommand
(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到service,那麼參數Intent將為null。(service因內存不足的情況下,殺死的進程才可以拉活,這里要特別注意,不是所有情況都可以拉活。第一次server被殺死後,會在5秒後拉活,第二次會在10秒後,第三次會在20秒後。之後就不會在拉活。第二種情況是獲得root許可權通過stop停止的,也是無法通過server拉活)
START_NOT_STICKY:「非粘性的」。使用這個返回值時,如果在執行完onStartCommand後,服務被異常kill掉,系統將會把它置為started狀態,系統不會自動重啟該服務,直到startService(Intent intent)方法再次被用;。
START_REDELIVER_INTENT:重傳Intent。使用這個返回值時,如果在執行完onStartCommand後,服務被異常kill掉,系統會自動重啟該服務,並將Intent的值傳入。
START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保證服務被kill後一定能重啟。
3、利用Native進程拉活,
4、利用JobScheler機制拉活:Android5.0之後提供的一個機制,他會監聽主進程的存活,如果死掉就會激活拉活進程。
5、利用賬號同步機制拉活:android系統有一個賬戶系統,設置一個自己的賬戶,android會定期喚醒賬戶更新服務。我們可以自己設定同步的事件間隔,且發起更新的是系統,不會受到任何限制。需要在 AndroidManifest 中定義賬號授權與同步服務。
Android 版本(Android N)中系統對賬戶同步這里做了變動,該方法不再有效。
缺點:
a.用戶會在系統設置的賬戶列表裡面看到一個不認識的賬戶;
b.同步的事件間隔是有限制的,最短1分鍾,見源碼,如果小雨60秒,置為60秒;
c.用戶可以卸載賬戶;
d.必須聯網!google提供這個組件是讓你同步賬戶信息,不聯網就不能保活!
⑦ android進程分為哪5種優先順序順序是怎樣的
Andrid 5個進程及重要優先順序前台進程>可見進程>服務進程>後台進程>空進程,
它們的回收優先順序則反之