Android的存儲系統—Vold與MountService分析(一)

来源:http://www.cnblogs.com/pepsimaxin/archive/2016/02/16/5193398.html
-Advertisement-
Play Games

Android的存儲系統(一) 看了很長時間Vold存儲模塊的相關知識,也死扣了一段時間的Android源碼,發現Android存儲系統所涉及的函數調用,以及Kernel與上層之間的Socket傳輸真的是讓人頭疼,除了需要整理整個架構的原理以外,還要反覆看源碼,真真的鬱悶。 鬱悶之餘,還是打算把自己


Android的存儲系統(一)

看了很長時間Vold存儲模塊的相關知識,也死扣了一段時間的Android源碼,發現Android存儲系統所涉及的函數調用,以及Kernel與上層之間的Socket傳輸真的是讓人頭疼,除了需要整理整個架構的原理以外,還要反覆看源碼,真真的鬱悶。

鬱悶之餘,還是打算把自己看過的經驗之貼和參考資料進行整理,以帖子的形式發出來,供碼神們參考,有不對的地方請指正,我們互相交流,下麵就進入主題。

Android的存儲系統主要由:SystemServer進程中的MountService和Vold進程中的VolumeManager組成。

它們管理著系統的存儲設備,執行各種操作,如:mount、unmount、format等。

圖1 Android存儲系統架構圖

圖2 Android存儲系統原理圖

【重要組成分析】

1、NetlinkManager

     全稱是NetlinkManager.cpp位於Android 4.x 源碼位置/system/vold/NetlinkManager.cpp。

     該類的主要通過引用NetlinkHandler類中的onEvent()方法來接收來自內核的事件消息,NetlinkHandler位於/system/vold/NetlinkHandler.cpp。

2、VolumeManager

     全稱是VolumeManager.cpp位於Android 4.x源碼位置/system/vold/VolumeManager.cpp。該類的主要作用是接收經過NetlinkManager處理過後的事件消息。

     因為我們這裡是SD的掛載,因此經過NetlinkManager處理過後的消息會分為五種,分別是:block、switch、usb_composite、battery、power_supply。

     這裡SD卡掛載的事件是block。

3、DirectVolume

     位於/system/vold/DirectVolume.cpp。該類的是一個工具類,主要負責對傳入的事件進行進一步的處理。

     block事件又可以分為:Add、Removed、Change、Noaction這四種。

4、Volume

     位於/system/vold/Volume.cpp,該類是負責SD卡掛載的主要類。Volume.cpp主要負責檢查SD卡格式,以及對複合要求的SD卡進行掛載,並通過Socket將消息SD卡掛載的消息傳遞給NativeDaemonConnector。

5、CommandListener

     該類位於位於/system/vold/CommandListener.cpp,通過vold socket與NativeDaemonConnector通信。

6、NativeDaemonConnector

     該類位於frameworks/base/services/java/com.android.server/NativeDaemonConnector.java。該類用於接收來自Volume.cpp 發來的SD卡掛載消息並向上傳遞。

7、MountService

     位於frameworks/base/services/java/com.android.server/MountService.java。

     MountService是一個服務類,該服務是系統服務,提供對外部存儲設備的管理、查詢等。在外部存儲設備狀態發生變化的時候,該類會發出相應的通知給上層應用。在Android系統中這是一個非常重要的類。

8、StorageManaer

     位於frameworks/base/core/java/andriod/os/storage/StorageManager.java。

     在該類的說明中有提到,該類是系統存儲服務的介面。在系統設置中,有Storage相關項,同時Setting也註冊了該類的監聽器。

     而StorageManager又將自己的監聽器註冊到了MountService中,因此該類主要用於上層應用獲取SD卡狀態。

 

【SD卡掛載流程】

1、Kernel發出SD卡插入uevent消息。

2、NetlinkHandler::onEvent()接收內核發出的uevent併進行解析。

3、VolumeManager::handleBlockEvent()處理經過第二步處理後的事件。

4、接下來調用DirectVolume::handleBlockEvent()。

在該方法中需要註意亮點:

(1)程式首先會遍歷mPath容器,尋找與event對應的sysfs_path是否存在於mPath容器中;

(2)針對event中的action有4種處理方式:Add、Removed、Change、Noaction。

 

 

 

5、經過上一步之後會調用DirectVolume::handleDiskAdded()方法,該方法中會廣播disk insert消息。

6、SocketListener::runListener()會接收DirectVolume::handleDiskAdded()廣播的消息。該方法主要完成對event中數據的獲取,通過Socket。

7、調用FrameworkListener::onDataAvailable()方法處理接收到的消息內容。

8、FrameworkListener::dispatchCommand()該方法用於分髮指令。

9、在FrameworkListener::dispatchCommand()方法中,通過runCommand()方法去調用相應的指令。

10、在/system/vold/CommandListener.cpp中有runCommand()的具體實現。在該類中可以找到這個方法:CommandListener::VolumeCmd::runCommand(),從字面意思上來看這個方法就是對Volume分髮指令的解析。該方法中會執行“mount”函數:vm>mountVolume(arg[2])。

11、mountVolume(arg[2])在VolumeManager::mountVolume()中實現,在該方法中調用v>mountVol()。

12、mountVol()方法在Volume::mountVol()中實現,該函數是真正的掛載函數。(在該方法中,後續的處理都在該方法中,在Mount過程中會廣播相應的消息給上層,通過setState()函數)。

13、setState(Volume::Checking);廣播給上層,正在檢查SD卡,為掛載做準備。

14、Fat::check();SD卡檢查方法,檢查SD卡是否是FAT格式。

15、Fat::doMount()掛載SD卡。

至此,SD的掛載已算初步完成,接下來應該將SD卡掛載後的消息發送給上層,在13中也提到過,在掛載以及檢查的過程中其實也有發送消息給上層的。

 

16、MountService的構造函數中會開啟監聽線程,用於監聽來自vold的socket信息。

     Thread thread = new Thread(mConnector,VOLD_TAG); thread.start();

17、mConnector是NativeDaemonConnector的對象,NativeDaemonConnector繼承了Runnable並Override了run方法。在run方法中通過一個while(true)調用ListenToSocket()方法來實現實時監聽。

18、在ListenToSocket()中,首先建立與Vold通信的Socket Server端,然後調用MountService中的onDaemonConnected()方法。

19、onDaemonConnected()方法是在介面INativeDaemonConnectorCallbacks中定義的,MountService實現了該介面並Override了onDaemonConnected()方法。該方法開啟一個線程用於更新外置存儲設備的狀態,主要更新狀態的方法也在其中實現。

20、然後回到ListenToSocket中,通過inputStream來獲取Vold傳遞來的event,並存放在隊列中。

21、然後這些event會在onDaemonConnected()通過隊列的”隊列.take()”方法取出。並根據不同的event調用updatePublicVolumeState()方法,在該方法中調用packageManagerService中的updateExteralState()方法來更新存儲設備的狀態。

22、更新是通過packageHelper.getMountService().finishMediaUpdate()方法來實現的。

23、在updatePublicVolumeState()方法中,更新後會執行如下代碼:

       bl.mListener.onStorageStateChanged();

在Android源碼/packages/apps/Settings/src/com.android.settings.deviceinfo/Memory.java代碼中,實現了StorageEventListener 的匿名內部類,並Override了onStorageStateChanged()方法。因此在updatePublicVolumeState()中調用onStorageStateChanged()方法後,Memory.java中也會收到。在Memory.java中收到以後會在Setting界面進行更新,系統設置—存儲中會更新SD卡的狀態。從而SD卡的掛載從底層到達了上層。

 

在下一個帖子中我會對Vold模塊的源碼以及MountService服務進行分析,包括main函數、NetlinkManager、NetlinkHandler、處理block類型的uevent、處理MountService命令、VolumeManager、NativeDaemonConnector等源碼,很快就會與大家見面,感謝支持,歡迎交流與指正!

 

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 捲標 , 屬性名稱 , 簡介 002 <! - - ... - -> 批註 003 <!> 跑馬燈 004 <marquee>...</marquee>普通捲動 005 <marquee behavior=slide>...</marquee>滑動 006 <marquee behavior=scr
  • 編寫好的CSS代碼能提升頁面的渲染速度。本質上,一條規則都沒有引擎解析的最快。MDN上將CSS選擇符歸拆分成四個主要類別,如下所示,性能依次降低。 ID 規則 Class 規則 標簽規則 通用規則 對效率普遍認識是從Steve Souders在2009年出版的《高性能網站建設進階指南》開始的,雖然S
  • 1.DOM:文檔對象模型DOM(Document Object Model)定義訪問和處理HTML文檔的標準方法。DOM 將HTML文檔呈現為帶有元素、屬性和文本的樹結構(節點樹)。 2.DOM的一些常用的屬性 2.1 通過ID獲取元素 (1)語法: document.getElementById(
  • 1.2、目的通過學習本文檔,能夠對jQuery有一個簡單的認識瞭解,清楚JQuery與其他JS框架的不同,掌握jQuery的常用語法、使用技巧及註意事項。二、使用方法在需要使用JQuery的頁面中引入JQuery的js文件即可。例如:<script type="text/javascript" sr
  • 前言:有時候我們需要獲取文件的MIMEType的信息,下麵就介紹關於獲取MIMEType的方法。 1、直接百度搜索關鍵字"MIMEType",你會找到,然後查吧: 2、用代碼獲取文件的MIMEType信息: 1 #import "GetMIMEType.h" 2 3 #import <MobileC
  • 前言:使用NSURLConnection實現文件上傳有點繁瑣。 本文並沒有介紹使用第三方框架上傳文件。 正文: 這裡先提供用於編碼測試的介面:http://120.25.226.186:32812 點擊進去你會發現到下麵: 最好該鏈接用Google瀏覽器打開,因為Google瀏覽器開啟開發者模式用起
  • Android開發,需要連接webservice,之前就想用谷歌提供的jar包,下載地址:http://pan.baidu.com/s/1hqMTUHe 把它下載下來粘貼到libs文件夾下即可: 網上有很多類似的方法,我嘗試了很多都沒有成功,最後發現是我下載的jar包有問題導致我一直卡在哪兒。 首先
  • 如下是快速索引的效果圖,是從網上下的實例。如圖實現的難點1:是最右側的索引是用自定義View來實現的,主要通過onDraw的方法將其畫出; 難點2:是如何拿到每個名字的首字母用的是pinyin4j-2.5.0.jar 將漢字轉化成拼音再去第一個字元;難點3:ListView的adapte不好實現 下
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...