Android 多進程介紹

      網友投稿 1178 2022-05-30

      推薦資源站:https://zhimalier.com/

      在Android中,默認情況下,同一應用的所有組件均運行在同一進程中,且大多數應用都不會改變這一點。不過,單進程開發并不是Android應用的全部,今天我們就來說說Android中的多進程開發以及多進程的使用場景。

      多進程介紹

      本篇文章內容基于Android Developer官網

      進程

      我們都知道Android系統是基于Linux改造而來的,進程系統也是一脈相承,進程,其實就是程序的具體實現。當程序第一次啟動,Android會啟動一個Linux進程(具體由Zygote fork出來)以及一個主線程,默認的情況下,所有組件都將運行在該進程內。同一個應用由系統分配一個獨立的Linux賬戶,該應用的產生的所有進程,都會是這同一個Linux賬戶。

      使用多進程

      在開發中,我們通常會使用修改清單文件的android:process來達到多進程的目的。activity、service、receiver?和?provider均支持android:process屬性,此屬性可以指定該組件應在哪個進程運行。如果android:process的value值以冒號開頭的話,那么該進程就是私有進程,如果是以其他字符開頭,那么就是公有進程,擁有相同?ShareUID?的不同應用可以跑在同一進程里,后續我會專門針對公私有進程做個試驗。另外,我們還可以通過設置application的android:process屬性,來設置所有組件的默認進程。

      至于創建進程的具體源碼分析,網上有一篇很詳細的文章,在這就不重復造輪子了,有需要的朋友可以前往?理解Android進程創建流程

      還有一種方法開啟進程,是通過JNI,利用C/C++,調用fork()方法來生成子進程,一般開發者會利用這種方法來做一些daemon進程,來實現防殺,保活等效果,不過不是太推薦,這么做,畢竟Android生態系統需要大家維護。

      進程生命周期

      剛剛聊了一下進程的“生”,作為一個生命周期,是時候該聊聊進程的“死”了。這里再次呼吁一下大家能正視進程的“死”,合理的利用多進程,適當的殺死不必要的進程才是本篇文章所關注的焦點,我們不要把“永生”作為自己的實現目標,Android設備內存就那么大,就像地球一樣,大家都永生了,生態系統就會破壞。那么Android系統是如何維護這個生態系統的呢?

      其實也是類似于現實生活中的優勝略汰,Android利用重要性層次結構,就是將最重要的保留,殺掉不重要的進程。Android將重要性層次結構分為5個層級,分為了:(以下5級描述節選自Android進程生命周期)

      前臺進程

      用戶當前操作所必需的進程。如果一個進程滿足以下任一條件,即視為前臺進程:

      托管用戶正在交互的?Activity(已調用?Activity?的?onResume()?方法)

      托管某個?Service,后者綁定到用戶正在交互的?Activity

      托管正在“前臺”運行的?Service(服務已調用?startForeground())

      托管正執行一個生命周期回調的?Service(onCreate()、onStart()?或?onDestroy())

      托管正執行其?onReceive()?方法的?BroadcastReceiver

      通常,在任意給定時間前臺進程都為數不多。只有在內存不足以支持它們同時繼續運行這一萬不得已的情況下,系統才會終止它們。 此時,設備往往已達到內存分頁狀態,因此需要終止一些前臺進程來確保用戶界面正常響應。

      這就需要依靠系統的資源。

      可見進程

      沒有任何前臺組件、但仍會影響用戶在屏幕上所見內容的進程。 如果一個進程滿足以下任一條件,即視為可見進程:

      托管不在前臺、但仍對用戶可見的?Activity(已調用其?onPause()?方法)。例如,如果前臺?Activity?啟動了一個對話框,允許在其后顯示上一?Activity,則有可能會發生這種情況。

      托管綁定到可見(或前臺)Activity?的?Service。

      Android 多進程介紹

      可見進程被視為是極其重要的進程,除非為了維持所有前臺進程同時運行而必須終止,否則系統不會終止這些進程。

      服務進程

      正在運行已使用?startService()?方法啟動的服務且不屬于上述兩個更高類別進程的進程。盡管服務進程與用戶所見內容沒有直接關聯,但是它們通常在執行一些用戶關心的操作(例如,在后臺播放音樂或從網絡下載數據)。因此,除非內存不足以維持所有前臺進程和可見進程同時運行,否則系統會讓服務進程保持運行狀態。

      后臺進程

      包含目前對用戶不可見的?Activity?的進程(已調用?Activity?的?onStop()?方法)。這些進程對用戶體驗沒有直接影響,系統可能隨時終止它們,以回收內存供前臺進程、可見進程或服務進程使用。 通常會有很多后臺進程在運行,因此它們會保存在 LRU (最近最少使用)列表中,以確保包含用戶最近查看的?Activity?的進程最后一個被終止。如果某個?Activity?正確實現了生命周期方法,并保存了其當前狀態,則終止其進程不會對用戶體驗產生明顯影響,因為當用戶導航回該?Activity?時,Activity?會恢復其所有可見狀態。 有關保存和恢復狀態的信息,請參閱?Activity文檔。

      空進程

      不含任何活動應用組件的進程。保留這種進程的的唯一目的是用作緩存,以縮短下次在其中運行組件所需的啟動時間。 為使總體系統資源在進程緩存和底層內核緩存之間保持平衡,系統往往會終止這些進程。

      根據進程中當前活動組件的重要程度,Android 會將進程評定為它可能達到的最高級別。例如,如果某進程托管著服務和可見?Activity,則會將此進程評定為可見進程,而不是服務進程。

      此外,一個進程的級別可能會因其他進程對它的依賴而有所提高,即服務于另一進程的進程其級別永遠不會低于其所服務的進程。 例如,如果進程 A 中的內容提供程序為進程 B 中的客戶端提供服務,或者如果進程 A 中的服務綁定到進程 B 中的組件,則進程 A 始終被視為至少與進程 B 同樣重要。

      由于運行服務的進程其級別高于托管后臺?Activity?的進程,因此啟動長時間運行操作的?Activity?最好為該操作啟動服務,而不是簡單地創建工作線程,當操作有可能比?Activity?更加持久時尤要如此。例如,正在將圖片上傳到網站的?Activity?應該啟動服務來執行上傳,這樣一來,即使用戶退出?Activity,仍可在后臺繼續執行上傳操作。使用服務可以保證,無論?Activity?發生什么情況,該操作至少具備“服務進程”優先級。 同理,廣播接收器也應使用服務,而不是簡單地將耗時冗長的操作放入線程中。

      Low Memory Killer

      進程按照狀態分完重要性之后,就要開始殺進程了。Android的Low Memory Killer基于Linux的OOM機制,在Linux中,內存是以頁面(page)為單位,當申請頁面分配不足的時候,系統會通過Low Memory Killer來殺掉bad進程,釋放內存。Low Memory Killer會根據進程的adj級別以及所占的內存,來決定是否殺掉該進程,adj越大,占用內存越多,進程越容易被殺掉。

      關于adj的分級,我們可以參考ProcessList.java,這里面的常量定義了ADJ的分級。(7.0以后的adj分級與之前的不太一樣(Processlist.java-Nougat),這個我們后續可以研究一下具體的改動是什么)

      adj分級:

      UNKNOWN_ADJ = 16

      級別最低級的進程,通常是被緩存的進程,但是系統也不清楚緩存的內容。

      CACHED_APP_MAX_ADJ = 15

      這是一個只托管不可見的活動的進程,因此可以在沒有任何中斷的情況下被殺死。

      CACHED_APP_MIN_ADJ = 9

      緩存進程,沒有英文解釋。

      SERVICE_B_ADJ = 8

      不活躍的服務,不想adj=5的服務那么活躍。

      PS:這里說一句,在root以后,有的系統優化大師,會把所有服務統一調成adj=8這個級別,來達到內存優化的目的,后面我們會說到。

      PREVIOUS_APP_ADJ = 7

      被切換的進程,一般是用戶前一個使用的進程。兩個應用來回切換,那么前一個應用一般adj設置為7。

      HOME_APP_ADJ = 6

      與主應用程序有交互的進程。

      SERVICE_ADJ = 5

      活躍的服務進程。

      HEAVY_WEIGHT_APP_ADJ = 4

      高權重進程

      BACKUP_APP_ADJ = 3

      正在備份的進程

      PERCEPTIBLE_APP_ADJ = 2

      可感知進程(通常是前臺Service進程)

      VISIBLE_APP_ADJ = 1

      可見進程

      FOREGROUND_APP_ADJ = 0

      前臺進程

      剩下的就是adj值為負數的進程,基本上都是系統集成,不在本文的討論范圍內。負數進程是不會被lmk殺掉的。

      如何查看進程優先級

      首先通過 adb shell ps 指令查找對應進程的pid

      然后通過 adb shell cat /proc/${pid}/oom_adj(設備需要root)返回對應進程的adj值。

      還可以把oom_adj替換成oom_score或者oom_score_adj來查看這兩項的數值,當oom_adj相同時,LowMemoryKiller會根據oom_score_adj和RSS內存大小來殺掉對應的進程。

      查看設備的內存臨界值

      我們可以通過adb shell cat 查看下面兩個文件

      /sys/module/lowmemorykiller/parameters/adj

      /sys/module/lowmemorykiller/parameters/minfree

      (這里請注意,這兩個文件是只可以寫入的,cat之前請先用chmod賦予權限。)

      adj 代表的是oom_score_adj的值,對應的minfree則代表內存臨界值。

      比如我的測試機小米4C測試機對應的值就是:

      adj: 0,58,117,176,529,1000

      這個值其實是oom_score_adj的值,用這個值*17再除1000四舍五入取整數,就是對應的adj的值,例如第二個值58即為 58*17/1000 = 1,對應的adj也就是1,所以這6個值對應的adj是0,1,2,3,9,15。1000默認就是15

      minfree: 18432,23040,27648,32256,56250,81250

      這個值是頁值,一頁等于4KB,換算成MB大概是72,90,108,126,220,318

      當可用內存小于318MB的時候,系統開始殺adj=15的進程,以此類推。

      小結

      以上,我們大概了解了一下Android進程、多進程、生命周期以及Low Memory Killer的相關知識。至于如何運用到實際開發當中,我們在下一篇文章《Android多進程使用場景》中繼續探討。

      Android HTTP 任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Python爬蟲:還在糾結買什么手機?pyquery庫給你參考答案
      下一篇:凍結2007excel表格前三行的方法步驟圖
      相關文章
      国产AV无码专区亚洲AWWW | 91亚洲精品麻豆| 亚洲AV永久无码区成人网站| 亚洲国产一区明星换脸| 国产亚洲精品欧洲在线观看| 亚洲a∨无码一区二区| 精品国产日韩亚洲一区在线| 亚洲av无码日韩av无码网站冲| 亚洲欧美日韩国产成人| 亚洲色偷偷偷综合网| 亚洲欧美日韩综合久久久| 亚洲依依成人亚洲社区| 亚洲国产精品18久久久久久| 亚洲日韩精品无码专区| 亚洲国产成人综合精品| 国产精品无码亚洲精品2021 | 中文字幕乱码亚洲无线三区 | 亚洲精华国产精华精华液网站| 亚洲人成人网站18禁| 亚洲av午夜电影在线观看| 亚洲AV无码AV日韩AV网站| 亚洲 另类 无码 在线| 亚洲精品高清在线| 国产午夜亚洲精品理论片不卡| 中文字幕精品亚洲无线码二区| 中文字幕亚洲一区| 亚洲成AV人片在线观看| 亚洲精品国产成人99久久| 久久综合亚洲色HEZYO社区| 亚洲国产中文在线二区三区免| 亚洲av成人一区二区三区| 亚洲乱妇熟女爽到高潮的片| 亚洲av日韩av永久无码电影| 亚洲成av人片在线观看天堂无码| 亚洲日韩在线第一页| 亚洲av中文无码乱人伦在线r▽| 亚洲最大成人网色| 亚洲av日韩av综合| 亚洲aⅴ天堂av天堂无码麻豆| 亚洲免费在线观看| 久久久青草青青亚洲国产免观 |