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)事件处理:
这里通过对两个连接的监听,完成对动态事件的处理,以及对上层应用操作的响应。
补充:
google原生Android 针对Vold的移植还需要改进:
1.U盘多分区挂载,原生的只同时支持4个分区挂载,这个就需要修改源码。
2.另外vold不支持 ntfs的挂载,linux 对ntfs的支持本来就不好,可以利用ntfs-3g来挂载,也需要修改代码。
3.vold还可以检测其他热插拔设备,主要获取其句柄。