Android的存儲系統(一)java
看了很長時間Vold存儲模塊的相關知識,也死扣了一段時間的Android源碼,發現Android存儲系統所涉及的函數調用,以及Kernel與上層之間的Socket傳輸真的是讓人頭疼,除了須要整理整個架構的原理之外,還要反覆看源碼,真真的鬱悶。android 鬱悶之餘,仍是打算把本身看過的經驗之貼和參考資料進行整理,以帖子的形式發出來,供碼神們參考,有不對的地方請指正,咱們互相交流,下面就進入主題。架構 |
Android的存儲系統主要由:SystemServer進程中的MountService和Vold進程中的VolumeManager組成。app
它們管理着系統的存儲設備,執行各類操做,如:mount、unmount、format等。socket
圖1 Android存儲系統架構圖ide
圖2 Android存儲系統原理圖函數
【重要組成分析】工具
一、NetlinkManagerspa
全稱是NetlinkManager.cpp位於Android 4.x 源碼位置/system/vold/NetlinkManager.cpp。線程
該類的主要經過引用NetlinkHandler類中的onEvent()方法來接收來自內核的事件消息,NetlinkHandler位於/system/vold/NetlinkHandler.cpp。
二、VolumeManager
全稱是VolumeManager.cpp位於Android 4.x源碼位置/system/vold/VolumeManager.cpp。該類的主要做用是接收通過NetlinkManager處理事後的事件消息。
由於咱們這裏是SD的掛載,所以通過NetlinkManager處理事後的消息會分爲五種,分別是:block、switch、usb_composite、battery、power_supply。
這裏SD卡掛載的事件是block。
三、DirectVolume
位於/system/vold/DirectVolume.cpp。該類的是一個工具類,主要負責對傳入的事件進行進一步的處理。
block事件又能夠分爲:Add、Removed、Change、Noaction這四種。
四、Volume
位於/system/vold/Volume.cpp,該類是負責SD卡掛載的主要類。Volume.cpp主要負責檢查SD卡格式,以及對複合要求的SD卡進行掛載,並經過Socket將消息SD卡掛載的消息傳遞給NativeDaemonConnector。
五、CommandListener
該類位於位於/system/vold/CommandListener.cpp,經過vold socket與NativeDaemonConnector通訊。
六、NativeDaemonConnector
該類位於frameworks/base/services/java/com.android.server/NativeDaemonConnector.java。該類用於接收來自Volume.cpp 發來的SD卡掛載消息並向上傳遞。
七、MountService
位於frameworks/base/services/java/com.android.server/MountService.java。
MountService是一個服務類,該服務是系統服務,提供對外部存儲設備的管理、查詢等。在外部存儲設備狀態發生變化的時候,該類會發出相應的通知給上層應用。在Android系統中這是一個很是重要的類。
八、StorageManaer
位於frameworks/base/core/java/andriod/os/storage/StorageManager.java。
在該類的說明中有提到,該類是系統存儲服務的接口。在系統設置中,有Storage相關項,同時Setting也註冊了該類的監聽器。
而StorageManager又將本身的監聽器註冊到了MountService中,所以該類主要用於上層應用獲取SD卡狀態。
【SD卡掛載流程】
一、Kernel發出SD卡插入uevent消息。
二、NetlinkHandler::onEvent()接收內核發出的uevent並進行解析。
三、VolumeManager::handleBlockEvent()處理通過第二步處理後的事件。
四、接下來調用DirectVolume::handleBlockEvent()。
在該方法中須要注意亮點: (1)程序首先會遍歷mPath容器,尋找與event對應的sysfs_path是否存在於mPath容器中; (2)針對event中的action有4種處理方式:Add、Removed、Change、Noaction。 |
五、通過上一步以後會調用DirectVolume::handleDiskAdded()方法,該方法中會廣播disk insert消息。
六、SocketListener::runListener()會接收DirectVolume::handleDiskAdded()廣播的消息。該方法主要完成對event中數據的獲取,經過Socket。
七、調用FrameworkListener::onDataAvailable()方法處理接收到的消息內容。
八、FrameworkListener::dispatchCommand()該方法用於分發指令。
九、在FrameworkListener::dispatchCommand()方法中,經過runCommand()方法去調用相應的指令。
十、在/system/vold/CommandListener.cpp中有runCommand()的具體實現。在該類中能夠找到這個方法:CommandListener::VolumeCmd::runCommand(),從字面意思上來看這個方法就是對Volume分發指令的解析。該方法中會執行「mount」函數:vm>mountVolume(arg[2])。
十一、mountVolume(arg[2])在VolumeManager::mountVolume()中實現,在該方法中調用v>mountVol()。
十二、mountVol()方法在Volume::mountVol()中實現,該函數是真正的掛載函數。(在該方法中,後續的處理都在該方法中,在Mount過程當中會廣播相應的消息給上層,經過setState()函數)。
1三、setState(Volume::Checking);廣播給上層,正在檢查SD卡,爲掛載作準備。
1四、Fat::check();SD卡檢查方法,檢查SD卡是不是FAT格式。
1五、Fat::doMount()掛載SD卡。
至此,SD的掛載已算初步完成,接下來應該將SD卡掛載後的消息發送給上層,在13中也提到過,在掛載以及檢查的過程當中其實也有發送消息給上層的。 |
1六、MountService的構造函數中會開啓監聽線程,用於監聽來自vold的socket信息。
Thread thread = new Thread(mConnector,VOLD_TAG); thread.start();
1七、mConnector是NativeDaemonConnector的對象,NativeDaemonConnector繼承了Runnable並Override了run方法。在run方法中經過一個while(true)調用ListenToSocket()方法來實現實時監聽。
1八、在ListenToSocket()中,首先創建與Vold通訊的Socket Server端,而後調用MountService中的onDaemonConnected()方法。
1九、onDaemonConnected()方法是在接口INativeDaemonConnectorCallbacks中定義的,MountService實現了該接口並Override了onDaemonConnected()方法。該方法開啓一個線程用於更新外置存儲設備的狀態,主要更新狀態的方法也在其中實現。
20、而後回到ListenToSocket中,經過inputStream來獲取Vold傳遞來的event,並存放在隊列中。
2一、而後這些event會在onDaemonConnected()經過隊列的」隊列.take()」方法取出。並根據不一樣的event調用updatePublicVolumeState()方法,在該方法中調用packageManagerService中的updateExteralState()方法來更新存儲設備的狀態。
2二、更新是經過packageHelper.getMountService().finishMediaUpdate()方法來實現的。
2三、在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等源碼,很快就會與你們見面,感謝支持,歡迎交流與指正! |