中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android對Linux系統的內存管理機制進行的優化是什么

發布時間:2021-11-30 09:53:42 來源:億速云 閱讀:135 作者:iii 欄目:大數據

這篇文章主要介紹“Android對Linux系統的內存管理機制進行的優化是什么”,在日常操作中,相信很多人在Android對Linux系統的內存管理機制進行的優化是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Android對Linux系統的內存管理機制進行的優化是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

Android對內存的使用方式同樣是“盡最大限度的使用”,這一點繼承了Linux的優點。只不過有所不同的是,Linux側重于盡可能多的緩存磁盤數據以降低磁盤IO進而提高系統的數據訪問性能,而 Android側重于盡可能多的緩存進程以提高應用啟動和切換速度。Linux系統在進程活動停止后就結束該進程,而Android系統則會在內存中盡量長時間的保持應用進程,直到系統需要更多內存為止 。這些保留在內存中的進程,通常情況下不會影響系統整體運行速度,反而會在用戶再次激活這些進程時,加快進程的啟動速度,因為不用重新加載界面資源了,這是Android標榜的特性之一。所以,Android現在不推薦顯式的“退出”應用。

那為什么內存少的時候運行大型程序會慢呢,原因是:在內存剩余不多時打開大型程序會觸發系統自身的進程調度策略,這是十分消耗系統資源的操作,特別是在一個程序頻繁向系統申請內存的時候。這種情況下系統并不會關閉所有打開的進程,而是選擇性關閉,頻繁的調度自然會拖慢系統。 

Android中的進程管理

說到Android的內存管理,就不得不提到進程管理,因為進程管理確確切切的影響著系統內存。在了解進程管理之前,我們首先了解一些基礎概念。

當某個應用組件啟動且該應用沒有運行其他任何組件時,Android 系統會使用單個執行線程為應用啟動新的 Linux 進程。默認情況下,同一應用的所有組件在相同的進程和線程(稱為“主”線程) 中運行。如果某個應用組件啟動且該應用已存在進程(因為存在該應用的其他組件),則該組件會在此進程內啟動并使用相同的執行線程。但是,你也可以安排應用中的其他組件在單獨的進程中運行,并為任何進程創建額外的線程。

Android應用模型的設計思想取自Web 2.0的Mashup概念,是 基于組件的應用設計模式。在該模型下,每個應用都由一系列的組件搭建而成,組件通過應用的配置文件描述功能。Android系統依照組件的配置信息,了解各個組件的功能并進行統一調度。這就意味著,來自不同應用的組件可以有機地結合在一起,共同完成任務,各個Android應用,只有明確的組件邊界,而不再有明確的進程邊界和應用邊界。這種設計,也令得開發者無需耗費精力去重新開發一些附屬功能,而是可以全身心地投入到核心功能的開發中。這樣不但提高了應用開發的效率,也增強了用戶體驗(比如電子郵件中選擇圖片作為附件的功能,可以直接調用專門的圖片應用的功能,不用自己從頭開發)。

系統不會為每個組件實例創建單獨的線程。運行于同一進程的所有組件均在 UI 線程中實例化,并且對每個組件的系統調用均由該線程進行分派。 因此,響應系統回調的方法(例如,報告用戶操作的 onKeyDown() 或生命周期回調方法)始終在進程的 UI 線程中運行(四大組件的各個生命周期回調方法都是在UI線程中觸發的)。 

進程的生命周期

Android的一個不尋常的基本特征是應用程序進程的生命周期并非是由應用本身直接控制的。相反,進程的生命周期是由系統決定的,系統會權衡每個進程對用戶的相對重要程度,以及系統的可用內存總量來確定。 比如說相對于終止一個托管了正在與用戶交互的Activity的進程,系統更可能終止一個托管了屏幕上不再可見的Activity的進程,否則這種后果是可怕的。因此,是否終止某個進程取決于該進程中所運行組件的狀態 。Android會有限清理那些已經不再使用的進程,以保證最小的副作用。

作為應用開發者,了解各個應用組件(特別是Activity、Service和BroadcastReceiver)如何影響應用進程的生命周期非常重要。不正確的使用這些組件,有可能導致系統在應用執行重要工作時終止進程。

舉個常見的例子, BroadcastReceiver 在其 onReceive() 方法中接收到Intent時啟動一個線程,然后從該函數返回。而一旦返回,系統就認為該 BroadcastReceiver 不再處于活動狀態,因此也就不再需要其托管進程(除非該進程中還有其他組件處于活動狀態)。這樣一來,系統就有可能隨時終止進程以回收內存,而這也最終會導致運行在進程中的線程被終止。此問題的解決方案通常是從 BroadcastReceiver 中安排一個 JobService ,以便系統知道在該進程中仍有活動的工作。

為了確定在內存不足時終止哪些進程,Android會根據進程中正在運行的組件以及這些組件的狀態,將每個進程放入 “重要性層次結構” 中。必要時,系統會首先殺死重要性最低的進程,以此類推,以回收系統資源。這就相當于為進程分配了優先級的概念。 

進程優先級

Foreground Process:前臺進程(正常不會被殺死)

用戶當前操作所必需的進程。有很多組件能以不同的方式使得其所在進程被判定為前臺進程。如果一個進程滿足以下任一條件,即視為前臺進程:

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

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

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

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

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

Visible Process:可見進程(正常不會被殺死

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

  • 托管不在前臺、但仍對用戶可見的 Activity(已調用其 onPause() 方法)。例如,啟動了一個對話框樣式的前臺 activity ,此時在其后面仍然可以看到前一個Activity。

運行時權限對話框就屬于此類。考慮一下,還有哪種情況會導致只觸發onPause而不觸發onStop?

  • 托管通過 Service.startForeground() 啟動的前臺Service。

Service.startForeground():它要求系統將它視為用戶可察覺到的服務,或者基本上對用戶是可見的。

  • 托管系統用于某個用戶可察覺的特定功能的Service,比如動態壁紙、輸入法服務等等。

可見進程被視為是極其重要的進程,除非為了維持所有前臺進程同時運行而必須終止,否則系統不會終止這些進程。如果這類進程被殺死,從用戶的角度看,這意味著當前 activity 背后的可見 activity 會被黑屏代替。

Service Process:服務進程(正常不會被殺死)

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

已經運行很久(例如30分鐘或更久)的Service,有可能被降級,這樣一來它們所在的進程就可以被放入Cached LRU列表中。這有助于避免一些長時間運行的Service由于內存泄漏或其他問題而消耗過多的RAM,進而導致系統無法有效使用緩存進程的情況。

Background / Cached Process:后臺進程(可能隨時被殺死)

這類進程一般會持有一個或多個目前對用戶不可見的 Activity (已調用 Activity 的 onStop() 方法)。它們不是當前所必須的,因此當其他更高優先級的進程需要內存時,系統可能 隨時終止 它們以回收內存。但如果正確實現了Activity的生命周期,即便系統終止了進程,當用戶再次返回應用時也不會影響用戶體驗:關聯Activity在新的進程中被重新創建時可以恢復之前保存的狀態。

在一個正常運行的系統中,緩存進程是內存管理中 唯一 涉及到的進程:一個運行良好的系統將始終具有多個緩存進程(為了更高效的切換應用),并根據需要定期終止最舊的進程。只有在非常嚴重(并且不可取)的情況下,系統才會到達這樣一個點,此時所有的緩存進程都已被終止,并且必須開始終止服務進程。

Android系統回收后臺進程的參考條件:

  • LRU算法:自下而上開始終止,先回收最老的進程。越老的進程近期內被用戶再次使用的幾率越低。殺死的進程越老,對用戶體驗的影響就越小。

  • 回收收益:系統總是傾向于殺死一個能回收更多內存的進程,因為在它被殺時會為系統提供更多內存增益,從而可以殺死更少的進程。殺死的進程越少,對用戶體驗的影響就越小。換句話說,應用進程在整個LRU列表中消耗的內存越少,保留在列表中并且能夠快速恢復的機會就越大。

這類進程會被保存在一個偽LRU列表中,系統會優先殺死處于列表尾部(最老)的進程,以確保包含用戶最近查看的 Activity 的進程最后一個被終止。這個LRU列表排序的確切策略是平臺的實現細節,但通常情況下,相對于其他類型的進程,系統會優先嘗試保留更有用的進程(比如托管用戶主應用程序的進程,或者托管用戶看到的最后一個Activity的進程,等等)。還有其他一些用于終止進程的策略:對允許的進程數量硬限制,對進程可以持續緩存的時間量的硬限制,等等。

在一個健康的系統中,只有緩存進程或者空進程會被系統隨時終止,如果服務進程,或者更高優先級的可見進程以及前臺進程也開始被系統終止(不包括應用本身糟糕的內存使用導致OOM),那就說明系統運行已經處于一個亞健康甚至極不健康的狀態,可用內存已經吃緊。

Empty Process:空進程(可以隨時殺死)

不含任何活躍組件的進程。保留這種進程的的唯一目的是用作緩存(為了更加有效的使用內存而不是完全釋放掉),以縮短下次啟動應用程序所需的時間,因為啟動一個新的進程也是需要代價的。只要有需要,Android會隨時殺死這些進程。

內存管理中對于前臺/后臺應用的定義,與用于Service限制目的的后臺應用定義不同。從Android 8.0開始,出于節省系統資源、優化用戶體驗、提高電池續航能力的考量,系統進行了前臺/后臺應用的區分,對于后臺service進行了一些限制。在該定義中,如果滿足以下任意條件,應用將被視為處于前臺:

>

  • 具有可見 Activity(不管該 Activity 已啟動還是已暫停)。

  • 具有前臺 Service。

  • 另一個前臺應用已關聯到該應用(不管是通過綁定到其中一個 Service,還是通過使用其中一個內容提供程序)。例如,如果另一個應用綁定到該應用的 Service,那么該應用處于前臺:IME 壁紙 Service 通知偵聽器 語音或文本 Service 如果以上條件均不滿足,應用將被視為處于后臺。 

Android系統如何評定進程的優先級

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

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

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

Home鍵退出和返回鍵退出的區別

Home鍵退出,程序保留狀態為后臺進程;而返回鍵退出,程序保留狀態為空進程,空進程更容易被系統回收。Home鍵其實主要用于進程間切換,返回鍵則是真正的退出程序。

從理論上來講,無論是哪種情況,在沒有任何后臺工作線程(即便應用處于后臺,工作線程仍然可以執行)的前提下,被置于后臺的進程都只是保留他們的運行狀態,并不會占用CPU資源,所以也不耗電。只有音樂播放軟件之類的應用需要在后臺運行Service,而Service是需要占用CPU時間的,此時才會耗電。所以說沒有帶后臺服務的應用是不耗電也不占用CPU時間的,沒必要關閉,這種設計本身就是Android的優勢之一,可以讓應用下次啟動時更快。然而現實是,很多應用多多少少都會有一些后臺工作線程,這可能是開發人員經驗不足導致(比如線程未關閉或者循環發送的Handler消息未停止),也可能是為了需求而有意為之,導致整個Android應用的生態環境并不是一片干凈。

到此,關于“Android對Linux系統的內存管理機制進行的優化是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

绥德县| 宣化县| 抚宁县| 扎鲁特旗| 邢台县| 鞍山市| 商洛市| 昭平县| 四平市| 班戈县| 古交市| 华池县| 黄浦区| 陆河县| 平利县| 鲜城| 睢宁县| 平顶山市| 格尔木市| 临邑县| 遂宁市| 江孜县| 西宁市| 通海县| 鲁甸县| 保靖县| 渑池县| 盐边县| 休宁县| 绩溪县| 巴林右旗| 彰化市| 千阳县| 夏邑县| 高邑县| 南开区| 江油市| 河曲县| 罗定市| 五寨县| 义乌市|