Android系統(tǒng)與其他操作系統(tǒng)有個很不一樣的地方,就是其他操作系統(tǒng)盡可能移除不再活動的進程,從而盡可能保證多的內(nèi)存空間,而Android系統(tǒng)卻是反其道而行之,盡可能保留進程。Android這樣設計有什么優(yōu)勢呢?又是通過怎樣的方法來管理這些被保留的進程的呢?Android用戶又該如何正確使用手機從而更好發(fā)揮Android系統(tǒng)所特有的優(yōu)勢呢?本文將一一為您解開這些謎團。

創(chuàng)新互聯(lián)成都企業(yè)網(wǎng)站建設服務,提供網(wǎng)站建設、做網(wǎng)站網(wǎng)站開發(fā),網(wǎng)站定制,建網(wǎng)站,網(wǎng)站搭建,網(wǎng)站設計,響應式網(wǎng)站建設,網(wǎng)頁設計師打造企業(yè)風格網(wǎng)站,提供周到的售前咨詢和貼心的售后服務。歡迎咨詢做網(wǎng)站需要多少錢:18980820575
? 本文的主要內(nèi)容如下:
一、Android進程管理的特殊設計
? ?Linux系統(tǒng)對進程的管理方式是一旦進程活動停止,系統(tǒng)就會結束該進程。盡管Android基于Linux Kernel,但在進程管理上,卻采取了另外一種獨特的設計:當進程活動停止時,系統(tǒng)并不會立刻結束它,而是會盡可能地將該進程保存在內(nèi)存中,在以后的某個時間,一旦需要該進程,系統(tǒng)就會立即打開它,而不用再做一些初始化操作。只有當剩余內(nèi)存不夠用了,為了維持新開啟的進程或者比較重要的進程的正常運行,系統(tǒng)才會選擇性地殺掉一些不重要的內(nèi)存,騰出內(nèi)存空間來,所以Android系統(tǒng)永遠不會有內(nèi)存不足的提示。
二、Android獨特進程管理設計的好處
? Android這種獨特的設計,也正是Android標榜的優(yōu)勢之一,這有兩個好處:
1、最大限度地提高內(nèi)存的使用率。
? ?比如,你的內(nèi)存是8G,如果每次使用完某個進程就殺掉,那么被使用的內(nèi)存基本上會始終保持在某個值,比如4G以內(nèi),那么內(nèi)存的使用率就總是保存在50%以內(nèi),剩余的4G內(nèi)存形同虛設,發(fā)揮用處的機會非常少。而Android的這種設計,就可以做到有多少內(nèi)存就用多少內(nèi)存,盡可能大地提高內(nèi)存使用率。同樣比如有8G內(nèi)存,使用完的進程仍保留在內(nèi)存中,累積下來,被使用的內(nèi)存就盡可能地會接近8G。
2、提高再次啟動時的啟動速度
? ?被駐留在內(nèi)存中不再活動的進程(后臺進程或空進程,后面會再講到),很多是經(jīng)常需要使用的,當再次使用該進程的時候,系統(tǒng)立即打開它,而不需要再重新初始化。例如,我們常用的瀏覽器,當暫時不再使用時,按下Home鍵或Back鍵,瀏覽器進程就變成了不再活動的進程。如果下次又要使用了,點擊多任務鍵,在最近使用應用列表中點擊瀏覽器即可,瀏覽器界面仍然保持著退出前的界面。但如果退出時把該進程移除了,那么再次使用時,就需要重新初始化,然后進入該應用,這往往會花費不少的時間。
三、Android進程的五個等級
? ? Android系統(tǒng)將盡量長時間地保持應用進程,但為了新建進程或運行更重要的進程,最終需要移除舊進程來回收內(nèi)存。為了確定保留或終止哪些進程,系統(tǒng)會根據(jù)進程中正在運行的組件以及這些組件的狀態(tài),將每個進程放入“重要性層次結構”中。必要時,系統(tǒng)會首先消除重要性最低的進程,然后是重要性略遜的進程,以此類推,以回收系統(tǒng)資源。該“重要性層級結構”將進程分為了五個等級:
1、前臺進程(foreground)
? ?前臺進程是指那些有組件正和用戶進行交互的應用程序的進程,也稱為Active進程。這些都是Android嘗試通過回收其他應用程序來使其保持相應的進程。這些進程的數(shù)量非常少,只有等到最后關頭才會終止這些進程,是用戶最不希望終止的進程。例如:而當你運行瀏覽器這類應用時,它們的界面就會顯示在前臺,它們就屬于前臺進程,當你按home鍵回到主界面,他們就變成了后臺程序。
? ?如果一個進程滿足以下任一條件,即視為前臺進程:
?(1)托管處于活動狀態(tài)的Activity,也就是說,它們位于前臺并對用戶事件進行響應,此時的情形為響應了Activity中的onResume()生命周期方法,但沒有響應onPause()。
?(2)托管正在執(zhí)行onReceive()方法處理事件程序的BroadcastReceiver。
?(3)托管正在執(zhí)行onStart()、onCreate()或onDestroy()事件處理程序的Service。
?(4)托管正在運行且被標記為在前臺運行的Service,即調(diào)用了該Service的startForeground()方法。
?(5)托管某個Service,且該Service正綁定在用戶正在交互的Activity的Service,即該Activity正處于活動狀態(tài)。
2、可見進程(visible)
? ? 沒有任何前臺組件、但仍然會影響用戶在屏幕上所見內(nèi)容的進程。如果一個進程滿足以下任一條件,即視為可見進程:
(1)托管不在前臺、但仍對用戶可見的Activity(已調(diào)用其onPause()方法)。例如:如果前臺Acitivty啟動了一個對話框,或者啟動了一個非全屏,亦或是一個透明的Activity,允許在其后顯示上一個Activity,則可能會發(fā)生這種情況,這類Activity不在前臺運行,也不能對用戶事件作出反應。
(2)托管綁定到可見Activity的Service。(官網(wǎng)上說是綁定到可見或前臺Activity,但筆者有一點疑問,這個和“前臺進程”中第(5)點相矛盾嗎,綁定到前臺Activity,那就是前臺進程了)
? ? 可見進程被視為是極其重要的進程,這類進程的數(shù)量也很少,只有在資源極度匱乏的環(huán)境下,為保證前臺進程繼續(xù)執(zhí)行時才會終止。
3、服務進程(Service)
? ? 正在運行已使用startService()方法啟動的Serice且不屬于上述兩個更高類別進程的進程。盡管服務進程與用戶所見內(nèi)容沒有直接關聯(lián),但是它們通常在執(zhí)行一些用戶關心的操作。因此,除非內(nèi)存不足以維持所有前臺進程和可見進程同時運行,否則系統(tǒng)會讓服務進程保持運行狀態(tài)。
? ?有些資料上面也稱這種進程為次要服務(Secondary Service),而屬于上述兩個更高類別的進程則被稱為主要服務,主要服務往往屬于系統(tǒng)進程,如撥號進程等,不可能被進程管理輕易終止。這里我們以Android開發(fā)者官網(wǎng)的稱呼為標準,稱為服務進程。
4、后臺進程(hidden)
? ?包含目前對用戶不可見的Activity,即該Activity調(diào)用了onStop()方法。這些進程對用戶體驗沒有直接影響,系統(tǒng)可能隨時終止它們,以回收內(nèi)存供上述三個更高級別的進程使用。通常會有很多后臺進程在運行,它們會保存在LRU(Least Recently Used,最近最少使用)列表中,以確保包含用戶最近查看的Activity的進程最后一個被終止。如果某個Activity正確實現(xiàn)了生命周期方法,并保存了其當前狀態(tài),則終止其進程不會對用戶體驗產(chǎn)生明顯影響,因為當用戶導航回該Activity時,Activity會恢復其所有可見狀態(tài)。
? ?這里讀者可以做個試驗,先開啟微信,進入到朋友圈界面, 然后點擊手機屏幕下方的導航欄中的Home按鍵進入到后臺,再點擊最近使用應用列表顯示按鈕(不同的手機位置不一樣,有的在Home鍵左邊,有的則在Home鍵右邊),在顯示的最近使用應用的列表中清理掉微信應用,最后再點擊桌面的微信圖標啟動微信,會發(fā)現(xiàn)顯示的界面仍然是朋友圈界面。
? ?后臺進程,我們可以簡單理解為,應用(只考慮只有Activity組件的情況)啟動后按Home鍵后被切換到后臺的進程。如瀏覽器、閱讀器等,當程序顯示在屏幕上時,它們所運行的進程即為前臺進程(foreground),一旦按home鍵(注意不是back鍵)返回到桌面,程序就停留在后臺,成為后臺進程。
5、空進程(empty)
? ?不含任何活動應用組件的進程。保留這種進程的唯一目的是用作緩存,以縮短下次再其中運行組件所需要的啟動時間。一般來說,當應用按back按鍵退出后應用后,就變成了一個空進程。比如BTE,在程序退出后,依然會在進程中駐留一個空進程,這個進程里沒有任何數(shù)據(jù)在運行,作用往往是提高該程序下次的啟動速度或者記錄程序的一些歷史信息。當系統(tǒng)內(nèi)存不夠用時,無疑,該進程是應該最先終止的。在最近使用應用列表中,可以看到按back鍵退出的應用。
? ?根據(jù)進程中當前活動組件的重要程度,Android會將進程評定為它可能達到的最高級別。通俗地說,就是如果一個進程同時擁有多個對應上述不同等級進程的組件時,會以最高的那個等級作為該進程的等級。例如,如果某進程托管著服務和可見Activity,則會將此進程評定為可見進程,而不是服務進程。
? ?此外,一個進程的級別可能會因為其他進程對它的依賴而有所提高,即服務于另一進程的進程其級別永遠不會低于其所服務的進程。例如,如果進程A中的內(nèi)容提供程序為進程B中的客戶端提供服務,或者如果進程A中的服務綁定到進程B中的組件,則進程A始終被視為至少與進程B同樣重要。
? ?由于運行服務的進程其級別高于托管后臺Activity的進程,因此啟動長時間運行操作的Activity最好為該操作啟動Service,而不是簡單地創(chuàng)建工作線程,當操作有可能比Activity更加持久時更應該如此。例如,正在將圖片上傳到網(wǎng)站的Activity應該啟動服務來執(zhí)行上傳,這樣一來,即使用戶退出Activity,仍可在后臺繼續(xù)執(zhí)行上傳操作。使用服務可以保證,無論Activity發(fā)生什么情況,該操作至少具備“服務進程”優(yōu)先級。如果某個Activity開啟了線程執(zhí)行耗時操作,當Activity退出時,該Activity的實例將不會釋放內(nèi)存資源,直到線程執(zhí)行完,這樣容易導致內(nèi)存泄漏。同理,廣播接收器也應該使用服務,而不是簡單地將耗時冗長的操作放入線程中。
四、進程移除順序的依據(jù)——閾(yu,第四聲)值
? ? 前面講到,內(nèi)存不夠用時,會根據(jù)進程的等級來決定優(yōu)先回收哪類進程。那么系統(tǒng)是根據(jù)什么來判斷需要移除這些進程的時機的呢?答案是閾值。
1、查看閾值
? ? 我們可以采用如下方法查看手機中各個等級進程的閾值(需要root權限),如第二排數(shù)據(jù)所示(其單位為頁):
? ?以第一個數(shù)據(jù)44032為例,計算方法為:
? ?1page=4KB=4*1024B=4096B
? ?44032page* 4048B/page =? 180355072B
? ?180355072B/1024/1024 = 172M
? ?即第一個等級的進程的閾值為172M。依次類推,閾值依次為:172M,190M,208M,226M,316M,415M。
? ?有必要說明一下,在Android開發(fā)者官方文檔中,是將Android應用進程分為了5個等級,但很多資料卻是分的6個等級,在后臺進程和空進程之間還有一個“內(nèi)容提供節(jié)點(content provider)進程”。內(nèi)容提供節(jié)點,沒有實體程序,僅提供內(nèi)容供別的程序去用 ,比如日歷供應節(jié)點,郵件供應節(jié)點等,在終止進程時,這類進程有比較高的優(yōu)先權。手機中應該是采用的6個等級的方式,如上六個數(shù)據(jù),正好對應著六個等級的進程,等級越高,閾值越低,即前臺進程閾值為172M,空進程為415M。當系統(tǒng)的剩余內(nèi)存只剩余不到415M的時候,系統(tǒng)首先會回收空進程,依次類推,只有剩余內(nèi)存不到172M了,才會去回收前臺進程,這樣就起到了優(yōu)化保護重要進程的作用。
五、Home鍵、Back鍵和多任務鍵
? ?Home鍵、Back鍵和多任務鍵,在手機屏幕的下方,這三個按鍵一般稱為導航欄,中間的按鈕為Home鍵,多任務鍵和Back鍵分別在其左右,一般根據(jù)手機品牌不同,左右位置也有所差異。
? ?在運行App的時候,如果按一下Home鍵或者Back鍵,都可以退到桌面,那么這兩者有什么區(qū)別呢?
Home鍵。按Home鍵的時候,App如果沒有Service開啟,會從一個前臺進程轉變?yōu)橐粋€后臺進程;如果有前臺service運行,就仍然是前臺進程,比如QQ音樂播放器等;如果是只有普通service運行,那么就轉變?yōu)榉者M程(參照前文中講的Android進程的5個級別)。
Back鍵。按Back鍵的時候,App如果沒有Service開啟,會從一個前臺進程轉變?yōu)橐粋€空進程;對于有Service運行的情況,和按Home鍵一樣。
? ? 后臺進程和空進程,都是駐留在后臺,處于暫停狀態(tài),也都是除了占用一部分內(nèi)存外,不占用其他如cpu等資源的,那么問題來了,為什么要設計后臺進程和空進程這兩種空進程呢?它們的區(qū)別到底在哪里呢?我們在前文講Android進程的5個等級的時候講到過,當剩余內(nèi)存不足的時候,系統(tǒng)會按照等級順序,優(yōu)先移除不太重要進程,以收回內(nèi)存供更重要的進程運行。那么,它們的區(qū)別就是,在剩余內(nèi)存不足時,會優(yōu)先移除空進程,再不足,才會移除空進程。所以,如果確實要退出某個應用一段時間內(nèi)不大使用了,如果這款應用有退出按鈕,就用應用自帶的退出功能;如果沒有,則最好按系統(tǒng)的Back鍵,這樣可以變成空進程,當系統(tǒng)要回收內(nèi)存時,就會優(yōu)先被回收,從而釋放的所占的資源。如果只是暫時退出去做點別的,過一會還要切換回來,或者對這款應用使用比較頻繁,那就使用Home鍵,因為相比于按Back鍵,這樣可以盡可能保住后臺進程,方便下次使用的時候快速啟動。
? ?當然,按Home鍵或Back鍵,對用戶來說,其實感覺不到差異,使用起來沒什么兩樣,但是,對于Android開發(fā)者來說,卻有必要作為常識來了解其中的道理和差異。無論是按Home鍵還是按Back鍵,在按多任務鍵的時候,都可以看到這些進程,如下圖所示。最下面的按鍵為清理按鍵,點擊后可以清除掉這些進程,回收內(nèi)存了,當然,前面也講了很多遍了,不建議這樣做。
2、修改閾值。
? ?可以采用命令:echo "44032,48640,53248,57856,80896,106241" /sys/module/lowmemorykiller/parameters/minfree來修改閾值,如下所示:
? ?重啟后,會恢復為原來的值。至于如何永久性修改該閾值,這里不深入探討,有興趣的童鞋可以自行研究,一般來說,就按照系統(tǒng)給定的默認值使用就可以了,沒特殊用途的話,沒必要修改。
? ?對于這一節(jié)閾值的內(nèi)容,暫時先講到這里,如果要更深入,可以自行多研究研究。筆者也沒有看到比較好的更深入的文章,所以也不好推薦,如果讀者看到比較好的,可以推薦給筆者,感激不盡。
六、開發(fā)者選項中的進程管理功能
? ? Android手機都帶有開發(fā)者選項,隱藏了很多功能,顧名思義,這些功能主要用于輔助開發(fā)者調(diào)試程序用的。其中有一些就是關于進程管理功能的,筆者這里簡單介紹一下其中兩款,如下圖紅框部分所示:
不保留活動。用戶離開以后即銷毀每個活動(Activity),這樣做使得后臺進程都被銷毀了。筆者試驗過幾款app,比如微信,瀏覽器,開啟/關閉“不保留活動”前后,按Home鍵后,再打開應用,有明顯的差別。當然,也試用了短信,DD打車,就沒看出起了什么作用。讀者若是感興趣可以深入研究研究,到時候在指導指導筆者!
后臺進程限制。如下圖所示,給出了后臺進程個數(shù)限制的選項。
七、進程管理軟件的使用
? ?Windows操作系統(tǒng)用戶往往總想著保留更多的內(nèi)存,在使用Android手機的時候,喜歡經(jīng)常清理后臺進程或空進程,而且清理完后,心里有一種特別爽的感覺,就像給家里做了一次大掃除一樣,筆者最初使用Android手機的時候也是這樣的心態(tài)-_-!基于這樣的心態(tài),一些進程清理軟件,很受普通用戶的青睞。其實這樣做卻正好抹殺了Android系統(tǒng)所標榜的優(yōu)勢,如前文所講到的。
? ?那么進程管理軟件有無必要呢?當然有的,只是需要注意使用場合。當需要運行大型程序的時候,可以手動關閉掉一些進程,騰出足夠的空間供大型程序使用,這樣就可以有效避免系統(tǒng)調(diào)用進程調(diào)度策略而引起的卡頓,這一點,第八大點第3小節(jié)中會有說明。而且由于開發(fā)者的原因,可能是程序寫得太爛,或程序容易出錯,或做不該做的動作,或是惡意程序,對于這類程序進程,手動移除也是有好處的。
? ?但如果是運行一些小程序,就完全沒有必要去預先殺進程了,完全可以交給系統(tǒng)自己管理。讀者可能會疑惑,因為小程序啟動的時候,也有可能會因為內(nèi)存不足而導致需要移除部分進程的情況。筆者認為,即便是內(nèi)存不足,小程序運行引起的調(diào)用進程調(diào)度策略測的次數(shù)非常少,要移除的進程也非常少,產(chǎn)生的影響不大。同時,我們也要意識到另外一點就是,無論是手動殺死進程還是自動殺進程,都需要cpu去執(zhí)行這些任務,所以也會拖慢手機和消耗電量。所以從這一點看,頻繁殺進程,也是一個不好的習慣。
八、答疑解惑
? ? 在以前沒有專門去了解Android進程管理機制的時候,甚至是在研究的過程中,筆者心里都經(jīng)常存在很多疑惑,以下整理了其中5個,不知道讀者您是否有也類似的困惑呢?
1、這么多駐留在內(nèi)存的進程,不會耗電嗎?
? ?大多數(shù)用慣了Windows操作系統(tǒng)的童鞋,看到Android系統(tǒng)盡可能保留不在活動的進程的設計,可能第一反應就是質(zhì)疑,難道這樣不會增加耗電量嗎?其實,但一個程序按home鍵變成后臺進程或者按back鍵退出變成空進程后,其實已經(jīng)被暫停了,只保留了運行狀態(tài),不會消耗cpu,一個程序會耗電,是因為它需要調(diào)用cpu來運算,現(xiàn)在不消耗cpu了,當然就不會耗電了。當然,開了service的應用就另當別論了,比如QQ音樂播放器,當按home鍵或back鍵后,音樂仍然播放,是因為它開啟了服務,而且是一個前臺服務,在后面我們會繼續(xù)講到,此時它是一個前臺進程,而不是后臺進程或空進程。
2、為什么一個不太app,運行時會占用很大的內(nèi)存呢?
我們經(jīng)常會碰到這樣一種現(xiàn)象,一個只有20M的App,運行起來的時候,卻會耗掉100M以上的內(nèi)存。一方面是,程序運行時為對象分配內(nèi)存,另一方面,是Android虛擬機的原因。Android中的應用啟動的時候,系統(tǒng)都會給它開啟一個獨立的虛擬機,這樣做的好處是可以避免虛擬機崩潰導致整個系統(tǒng)崩潰,代價就是耗用更多的內(nèi)存。
3、為什么內(nèi)存少的時候,運行大型程序會卡頓呢?
? ? 當剩余內(nèi)存不多時,打開大型程序,系統(tǒng)會觸發(fā)自身的進程調(diào)度策略,去移除一些等級比較低的進程來回收內(nèi)存,以供大型程序運行。而這個進程調(diào)度策略在決定哪些進程需要被移除的過程,是一個十分消耗資源的操作,特別是一個程序頻繁像系統(tǒng)申內(nèi)存的時候,這樣就導致了系統(tǒng)的卡頓。
4、應用開得太多了,手機變慢,是因為內(nèi)存被占用太多嗎?
? ? 其實手機變慢的根本原因是cpu被耗用太多,而不是內(nèi)存占用太多,因為真正執(zhí)行程序所要完成的任務的最終執(zhí)行者是CPU,而不是內(nèi)存(RAM)。在內(nèi)存足夠的情況下,如果系統(tǒng)中占用cpu的進程太多,那無疑cpu總有忙不過來的時候,那肯定就會變慢了。這就好比,在一條道路上駕車,道路就像內(nèi)存,車的引擎就像cpu,如果車的引擎的動力不夠,或者承載的貨物太多,車都跑不快,即便是道路上一路暢通無阻,也無濟于事。所以,內(nèi)存占用多少并不重要,只要道路提供給車輛前行的空間是足夠的,手機變慢的責任,就和內(nèi)存無關了。這個比喻用來解釋第三點也很恰當,道路提供的車輛前進的空間無法滿足車輛所必需的空間時,就需要交通機制花時間來調(diào)節(jié)交通,給這輛車提供足夠的空間,而在此期間,這輛車只能乖乖候著。
5、Android手機越用越慢,是什么原因呢?
Android手機常常是越用越慢,即使是恢復出廠設置,也無法改變這個現(xiàn)象。手機越用越慢,主要由如下幾個原因:(1)虛擬機機制問題。這一點在上一個問題中也提到了,在Android4.4以前的系統(tǒng),使用的是Dalvik虛擬機,它的設計機制有缺陷,就是越用越慢;在Android4.4系統(tǒng)中有切換按鈕,可以在Art虛擬機和Dalvik虛擬機之間切換;在Android4.4以后的系統(tǒng)就徹底拋棄了Dalvik而全面使用Art。(2)開啟了太多的服務,導致耗用太多的CPU。隨著手機開機使用時間的增長,應用使用越來越多,很多應用看似退出了,而其實后臺可能開了不少的服務,而他們可能還沒有關閉。這些服務正在執(zhí)行一些操作,會消耗CPU,而CPU才是手機變慢的根本原因。 而且Android app比較開放的,有很多不良應用充斥其中,可能對服務處理不當,濫用服務等,增加系統(tǒng)中的服務。(3)系統(tǒng)頻繁調(diào)用自身的進程調(diào)度算法。這一點在前面已經(jīng)說明了,這里不再贅述。(4)手機硬件的自然老化
從 Android 6.0 開始,按照是否需要動態(tài)申請分為 普通權限 和 特殊權限
特殊權限 需要程序運行時申請并通過之后才能使用,或者程序安裝為系統(tǒng)應用或系統(tǒng)簽名。
注意:
1、動態(tài)申請也需要在清單文件中配置(AndroidMenifest.xml)
2、權限是分組的,同一組的權限申請其中一個,同組的權限就全部都申請了
特殊權限共有 9 組:
9 組具體權限列表:
普通權限在清單文件配置(AndroidMenifest.xml)即可使用
(1)在 AndroidMenifest.xml 清單文件中申請
(2)單個申請
(2)批量申請
(3)回調(diào)處理
部分內(nèi)容出至林學森的Android內(nèi)核設計思想。
Android官網(wǎng)內(nèi)存管理
部分出至
Android本質(zhì)是Linux所以先從Linux說起。
Linux的內(nèi)存管理為系統(tǒng)中所有的task提供可靠的內(nèi)存分配、釋放和保護機制。
核心:
虛擬內(nèi)存
內(nèi)存分配與釋放
內(nèi)存保護
將外存儲器的部分空間作為內(nèi)存的擴展,如從硬盤劃出4GB大小。
當內(nèi)存資源不足時,系統(tǒng)按照一定算法自動條形優(yōu)先級低的數(shù)據(jù)塊,并把他們存儲到硬盤中。
后續(xù)如果需要用到硬盤中的這些數(shù)據(jù)塊,系統(tǒng)將產(chǎn)生“缺頁”指令,然后把他們交換回內(nèi)存中。
這些都是由操作系統(tǒng)內(nèi)核自動完成的,對上層應用”完全透明“。
每個進程的邏輯地址和物理地址都不是直接對應的,任何進程都沒辦法訪問到它管轄范圍外的內(nèi)存空間——即刻意產(chǎn)生的內(nèi)存越界與非法訪問,操作系統(tǒng)也會馬上阻止并強行關閉程序,從而有力的保障應用程序和操作系統(tǒng)的安全和穩(wěn)定。
一旦發(fā)現(xiàn)系統(tǒng)的可用內(nèi)存達到臨界值,機會按照優(yōu)先級順序,匆匆低到高逐步殺掉進程,回收內(nèi)存。
存儲位置:/proc/PID/oom_score
優(yōu)先級策略:
進程消耗的內(nèi)存
進程占用的CPU時間
oom_adj(OOM權重)
Android平臺運行的前提是可用內(nèi)存是浪費的內(nèi)存。它試圖在任何時候使用所有可用的內(nèi)存。例如,系統(tǒng)會在APP關閉后將其保存在內(nèi)存中,以便用戶可以快速切換回它們。出于這個原因,Android設備通常運行時只有很少的空閑內(nèi)存。在重要系統(tǒng)進程和許多用戶應用程序之間正確分配內(nèi)存內(nèi)對存管理是至關重要。
Android有兩種主要的機制來處理低內(nèi)存的情況:內(nèi)核交換守護進程(kernel swap daemon)和低內(nèi)存殺手(low-memory killer)。
當用戶在APP之間切換時,Android會在最近使用的(LRU)緩存中保留不在前臺的APP,即用戶看不到的APP,或運行類似音樂播放的前臺服務。如果用戶稍后返回APP,系統(tǒng)將重用該進程,從而使APP切換更快。
如果你的APP有一個緩存進程,并且它保留了當前不需要的內(nèi)存,那么即使用戶不使用它,你的APP也會影響系統(tǒng)的整體性能。由于系統(tǒng)內(nèi)存不足,它會從最近使用最少的進程開始殺死LRU緩存中的進程。該系統(tǒng)還負責處理占用最多內(nèi)存的進程,并可以終止這些進程以釋放RAM。
當系統(tǒng)開始終止LRU緩存中的進程時,它主要是自底向上工作的。系統(tǒng)還考慮哪些進程消耗更多的內(nèi)存,從而在終止時為系統(tǒng)提供更多的內(nèi)存增益。你在LRU列表中消耗的內(nèi)存越少,你就越有可能留在列表中并能夠快速恢復。
為了滿足RAM的所有需求,Android嘗試共享RAM來跨進程通信。它可以做到以下方式:
Android設備包含三種不同類型的內(nèi)存:RAM、zRAM和storage。
注意:CPU和GPU都訪問同一個RAM。
內(nèi)存被拆分成頁。通常每頁有4KB的內(nèi)存。
頁面被認為是空閑的或已使用的。
空閑頁是未使用的RAM。
已使用頁是系統(tǒng)正在積極使用的RAM,分為以下類別:
干凈的頁面(Clean pages)包含一個文件(或文件的一部分)的一份精確副本存在存儲器上。當一個干凈的頁面不再包含一個精確的文件副本(例如,來自應用程序操作的結果)時,它就變成了臟頁。可以刪除干凈的頁,因為它們始終可以使用存儲中的數(shù)據(jù)重新生成;不能刪除臟頁(Dirty pages),否則數(shù)據(jù)將丟失。
內(nèi)核跟蹤系統(tǒng)中的所有內(nèi)存頁。
當確定一個應用程序正在使用多少內(nèi)存時,系統(tǒng)必須考慮shared pages。APP訪問相同的服務或庫將可能共享內(nèi)存頁。例如,Google Play Services 和一個游戲APP可能共享一個位置服務。這使得很難確定有多少內(nèi)存屬于這個服務相對于每個APP。
當操作系統(tǒng)想要知道所有進程使用了多少內(nèi)存時,PSS非常有用,因為頁面不會被多次計數(shù)。PSS需要很長時間來計算,因為系統(tǒng)需要確定哪些頁面是共享的,以及被有多少進程。RSS不區(qū)分共享頁面和非共享頁面(使計算速度更快),更適合于跟蹤內(nèi)存分配的更改。
內(nèi)核交換守護進程(kswapd)是Linux內(nèi)核的一部分,它將使用過的內(nèi)存轉換為空閑內(nèi)存。當設備上的空閑內(nèi)存不足時,守護進程將變?yōu)榛顒訝顟B(tài)。Linux內(nèi)核保持低和高的可用內(nèi)存閾值。當空閑內(nèi)存低于低閾值時,kswapd開始回收內(nèi)存。當空閑內(nèi)存達到高閾值,kswapd將停止回收內(nèi)存。
kswapd可以通過刪除干凈的頁面來回收干凈的頁面,因為它們有存儲器支持并且沒有被修改。如果進程試圖尋址已刪除的干凈頁,則系統(tǒng)會將該頁從存儲器復制到RAM。此操作稱為請求分頁。
kswapd將緩存的私有臟頁(private dirty pages)和匿名臟頁(anonymous dirty pages)移動到zRAM進行壓縮。這樣做可以釋放RAM中的可用內(nèi)存(空閑頁)。如果進程試圖觸摸zRAM中臟頁,則該頁將被解壓縮并移回RAM。如果與壓縮頁關聯(lián)的進程被終止,則該頁將從zRAM中刪除。
如果可用內(nèi)存量低于某個閾值,系統(tǒng)將開始終止進程。
lmkd實現(xiàn)源碼要在system/core/lmkd/lmkd.c。
lmkd會創(chuàng)建名為lmkd的socket,節(jié)點位于/dev/socket/lmkd,該socket用于跟上層framework交互。
小結:
LMK_TARGET: AMS.updateConfiguration() 的過程中調(diào)用 updateOomLevels() 方法, 分別向/sys/module/lowmemorykiller/parameters目錄下的minfree和adj節(jié)點寫入相應信息;
LMK_PROCPRIO: AMS.applyOomAdjLocked() 的過程中調(diào)用 setOomAdj() 向/proc/pid/oom_score_adj寫入oom_score_adj后直接返回;
LMK_PROCREMOVE: AMS.handleAppDiedLocked 或者 AMS.cleanUpApplicationRecordLocked() 的過程,調(diào)用remove(),目前不做任何事,直接返回;
為了進一步幫助平衡系統(tǒng)內(nèi)存并避免終止APP進程,可以Activity類中實現(xiàn)ComponentCallbacks2接口。提供的onTrimMemory()回調(diào)方法允許APP在前臺或后臺偵聽與內(nèi)存相關的事件,然后釋放對象以響應應用程序生命周期或表明系統(tǒng)需要回收內(nèi)存的系統(tǒng)事件。
onTrimMemory()回調(diào)是在Android 4.0(API級別14)中添加的。
對于早期版本,可以使用onLowMemory(),它大致相當于TRIM_MEMORY_COMPLETE事件。
一個專門的驅動。(Linux Kernel 4.12 已移除交給kswapd處理)。
很多時候,kswapd無法為系統(tǒng)釋放足夠的內(nèi)存。在這種情況下,系統(tǒng)使用onTrimMemory()通知APP內(nèi)存不足,應該減少其分配。如果這還不夠,內(nèi)核將開始終止進程以釋放內(nèi)存,它使用低內(nèi)存殺手(LMK)來完成這個任務。
為了決定要終止哪個進程,LMK使用一個名為oom_adj_score的“out of memory”分數(shù)來確定運行進程的優(yōu)先級,高分的進程首先被終止。
后臺應用程序首先被終止,系統(tǒng)進程最后被終止。
下表列出了從高到低的LMK評分類別。第一排得分最高的項目將首先被殺死:
Android Runtime(ART)和Dalvik虛擬機使用分頁(Paging)和內(nèi)存映射(mmapping)來管理內(nèi)存。應用程序通過分配新對象或觸摸已映射頁面來修改內(nèi)存都將保留在RAM中,并且不能被調(diào)出。應用程序釋放內(nèi)存的唯一方式是垃圾收集器。
使用android手機的用戶可能都安裝了任務管理的軟件,使用android手機真的有必要安裝結束任務的軟件嗎?大家在使用中也都發(fā)現(xiàn)了,很多軟件在被結束后,馬上就會又出現(xiàn)在任務列表里,或是稍等一會自己也會出現(xiàn),任務管理不停的結束后臺程序,也沒見給手機的運行速度帶來多少提升,這是為什么呢?
其實大家不用那么在意android手機剩余內(nèi)存的大小。很多人都是把使用其他系統(tǒng)的習慣帶到了android手機上,不是所有的智能手機系統(tǒng)都一樣的。android大多數(shù)應用沒有退出的設計其實是有道理的,這和系統(tǒng)對進程的調(diào)度機制有關系。如果你知道java,就能更清楚這機制了。其實和java的垃圾回收機制類似,系統(tǒng)有一個規(guī)則來回收內(nèi)存。進行內(nèi)存調(diào)度有個閥值,只有低于這個值系統(tǒng)才會按一個列表來關閉用戶不需要的東西。當然這個值默認設置得很小,所以你會看到內(nèi)存老在很少的數(shù)值徘徊。但事實上他并不影響速度。相反加快了下次啟動應用的速度。這本來也是android的優(yōu)勢之一,如果人為去關閉進程,沒有太大必要。特別是自動關進程的軟件。
可能有人會說了,那為什么內(nèi)存少的時候運行大型程序會慢呢?其實很簡單,在內(nèi)存剩余不多時打開大型程序,會觸發(fā)系統(tǒng)自身的調(diào)進程調(diào)度策略,這是十分消耗系統(tǒng)資源的操作,特別是在一個程序頻繁向系統(tǒng)申請內(nèi)存的時候。這種情況下系統(tǒng)并不會關閉所有打開的進程,而是選擇性關閉,頻繁的調(diào)度自然會拖慢系統(tǒng)。
那么,進程管理軟件到底還有存在的價值嗎?其實還是有的,在運行大型程序之前,你可以手動關閉一些進程釋放內(nèi)存,可以顯著的提高運行速度。但一些小程序,完全可交由系統(tǒng)自己管理。很多朋友還有個疑問,如果不關程序是不是會更耗電?這里也解釋一下,android的應用在被切換到后臺時,它其實已經(jīng)被暫停了,并不會消耗cpu資源,只保留了運行狀態(tài)。所以為什么有的程序切出去重新進入,還會到主界面。但是,一個程序如果想要在后臺處理些東西,如音樂播放,它就會開啟一個服務,服務可在后臺持續(xù)運行,所以在后臺耗電的也只有帶服務的應用了。這個在進程管理軟件里能看到,名字是service。所以沒有帶服務的應用在后臺是完全不耗電的,沒有必要關閉。這種設計本來就是一個非常好的設計,下次啟動程序時,會更快,因為不需要讀取界面資源,何必要關掉他們抹殺這個android的優(yōu)點呢?
還有一點,為什么android應用看起來那么耗內(nèi)存?大家知道,android上的應用是java,當然需要虛擬機,而android上的應用是帶有獨立虛擬機的,也就是每開一個應用就會打開一個獨立的虛擬機。這樣設計的原因是可以避免虛擬機崩潰導致整個系統(tǒng)崩潰,但代價就是需要更多內(nèi)存。
至于為什么開了大程序或者開了好幾個程序之后切換會變慢,具體分析如下:
已經(jīng)開啟了一個大程序,占用70%內(nèi)存,如果再想運行一個程序,此時還需要50%的內(nèi)存,則就需要一個從大程序占用的內(nèi)存中釋放或者壓縮的過程,所以表現(xiàn)出來的就是慢一會兒。
已經(jīng)開啟了幾個程序共占用內(nèi)存80%,運行新程序時又需要20%的內(nèi)存,系統(tǒng)內(nèi)存因為沒見過剩余0的時候,也就是應該剩一部分空閑內(nèi)存,那么就需要從之前開啟的這幾個程序中選擇一個或者幾個來關閉,這一過程也需要耗費系統(tǒng)資源,所以會慢一會兒。也就是說你手動去結束程序的時候,就是替系統(tǒng)在釋放內(nèi)存,就算你不去結束,在需要內(nèi)存的時候系統(tǒng)也會自動結束程序釋放內(nèi)存。
不在后臺運行的程序(沒服務的),即使不結束也不會耗電。在后臺運行的.(有服務的)程序,如一些播放器或實時監(jiān)控的軟件,自然會耗電。這就說明結束進程并不是沒用,我們只需要看哪個帶服務耗電哪個程序后臺一直在運行,看服務就能看出來,這樣的軟件如果用不到的時候就結束了吧。
以QQ舉例,正常的退出,會在進程管理里留下qq的運行過的狀態(tài),但不耗電不占 cpu,如果你只是切換出去(按房子鍵而不是退出)那么自然會耗電,因為程序還在運行,QQ還在線呢。
這里就有個要注意的地方了,雖然房子鍵和那個返回鍵都可以將程序切換出去,但是兩者的效果差異是很大的,返回鍵可以視作程序已經(jīng)退出了,而按房子鍵,則是將程序切換到了后臺來運行,軟件并沒有退出哦!
以上這些設計都是為了確保了android的穩(wěn)定性,正常情況下最多單個程序崩潰,但整個系統(tǒng)不會崩潰,也永遠沒有內(nèi)存不足的提示出現(xiàn)。大家可能是被windows毒害得太深了,總想保留更多的內(nèi)存,但實際上這并不一定會提升速度,相反卻喪失了程序啟動快的這一系統(tǒng)特色,得不償失。大家不妨換種觀念習慣來使用android系統(tǒng)。
文章標題:android管理,android管理項目
瀏覽路徑:http://www.yijiale78.com/article22/dschcjc.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、定制網(wǎng)站、網(wǎng)站改版、網(wǎng)站內(nèi)鏈、網(wǎng)站導航、做網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)