Android Vold(Volume Daemon)
負責大容量存儲設備掛載和刪除的守護進程。
服務在init.rc中被開啓:
- service vold /system/bin/vold
- socket vold stream 0660 root mount
本文主要分爲兩個部分:
·Vold 的架構分析
·Vold的功能總結
1.Vold的架構分析
Android Vold ,一方面負責接受內核發送的關於外部存儲設備加載和刪除的信息,然後將信息發送給framework層的MountService;另一方面負責執行MountService發送的命令。
這些cmd和mes的傳遞主要是通過Socket通信來實現(Socket的通信的具體細節這裏不再贅述)。
下面從代碼的角度簡要分析這一過程的實現:
1.1在vold.c中,首先建立和framework層的通信:
|
其中,VOLD_SOCKET在init進程中創建,android_get_control_socket()主要是獲取VOLD_SOCKET的文件描述符。
Listern()主要用於監聽來自其他framework層的Socket連接請求。
當framewok層,MountService開啓之後,會創建一個新的線程。在class MountService 的構造方法中:
- if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
- Thread thread = new Thread(mListener, MountListener.class.getName());
- thread.start();
- }
class MountListener 實現了Runnable接口,在它繼承的run()方法中創建了一個無限循環:
|
在listenToSocket()方法中:
|
首先,實例化一個本地的LocalSocket 用於與Vold的通信,其次建立與VOLD_SOCKET的連接。然後再建立一個文件輸入流,用於保存Vold傳來的mes到buff中。最後,在一個無線循環中讀取buff的內容,並執行handleEvent()。
在handleEvent()中通過if else語句對傳來的事件做相應處理
- if (event.equals(VOLD_EVT_UMS_ENABLED)) {
- ................
- } else if (event.equals(VOLD_EVT_UMS_DISABLED)) {
- ................
- } else if (event.equals(VOLD_EVT_EXTERNAL_UMS_CONNECTED)) {
- ...............
- mService.notifyUmsConnected(path);
- .....................
- } else if (event.equals(VOLD_EVT_UMS_CONNECTED)) {
- ...........................
- mService.notifyUmsConnected(path);
- } else if (event.equals(VOLD_EVT_EXTERNAL_UMS_DISCONNECTED)) {
- .........................
對於其中一個事件的處理,例如.notifyUmsConnected():
最後,將處理之後需要執行的命令發送給vold。
到現在爲止,我們就建立了vold 與MountService之間的通信。
1.2建立與內核的socket通信
|
|
創建一個uevent_sock,建立與內核的通信。setsockopt()函數主要用於設置uevent_sock的選項,bind()用於將內核的socket與uevent_sock進行地址的綁定。
1.3掛載現有存儲設備
volmgr_bootstrap()函數首先解析配置文件vold.conf;
最後會將需要掛載的設備信息放在一個全局變量的鏈表中val_root
static volume_t *vol_root = NULL;
1.4掛載mmc/sdcard卡
- volmgr_bootstrap();
- simulate_uevent()確定uevent的action是'add','remove'還是'change';
- if ((rc = volmgr_readconfig("/system/etc/vold.conf")) < 0) {
- LOGE("Unable to process config");
- return rc;
- }
mmc_bootstrap() |
dipatch_uevent():根據uevent->subsystem確定uevent處理的句柄。
- struct uevent {
- const char *action;
- const char *path;
- const char *subsystem;
- const char *firmware;
- int major;
- int minor;
- };
最終的掛載操作在MountService開啓之後實現。
1.5 usb大容量存儲的處理ums_bootstrap()
1.6 switch_bootstrap()
1.7主服務(死循環)
- struct uevent_dispatch {
- char *subsystem;
- int (* dispatch) (struct uevent *);
- };
|
2.Vold的功能總結
1)創建連接:
在vold作爲一個守護進程,一方面接受驅動的信息,並把信息傳給應用層;另一方面接受上層的命令並完成相應操作。
所以這裏的連接一共有兩條:
·vold socket: 負責vold與應用層的信息傳遞;
·訪問udev的socket: 負責vold與底層的信息傳遞;
這兩個連接都是在進程的一開始完成創建的。
2)引導:
這裏主要是在vold啓動時,對現有外設存儲設備的處理。
·首先,要加載並解析vold.conf,並檢查掛載點是否已經被掛載;
·其次,執行MMC卡掛載;
·最後,處理USB大容量存儲。
3)事件處理:
這裏通過對兩個連接的監聽,完成對動態事件的處理,以及對上層應用操作的響應。
補充:
Telechips比較google原生Android 針對Vold的移植主要在以下兩方面:
1.Telchips支持多種存儲設備,例如nand,sata,scsi,mmc/sd;從代碼角度而言,主要增加了對這些設備事件的處理句柄;
2.Telchips加入了對ntfs的支持,主要增加了三個處理函數:ntfs_check(),ntfs_identify()和ntfs_mount();