Android Vold(Volume Daemon)
负责大容量存储设备挂载和删除的守护进程。
服务在init.rc中被开启:
- service vold /system/bin/vold
- socket vold stream 0660 root mount
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层的通信:
- if ((door_sock = android_get_control_socket(VOLD_SOCKET)) < 0) {
- LOGE("Obtaining file descriptor socket '%s' failed: %s",
- VOLD_SOCKET, strerror(errno));
- exit(1);
- }
- if (listen(door_sock, 4) < 0) {
- LOGE("Unable to listen on fd '%d' for socket '%s': %s",
- door_sock, VOLD_SOCKET, strerror(errno));
- exit(1);
- }
if ((door_sock = android_get_control_socket(VOLD_SOCKET)) < 0) { LOGE("Obtaining file descriptor socket '%s' failed: %s", VOLD_SOCKET, strerror(errno)); exit(1); } if (listen(door_sock, 4) < 0) { LOGE("Unable to listen on fd '%d' for socket '%s': %s", door_sock, VOLD_SOCKET, strerror(errno)); exit(1); }
|
其中,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();
- }
if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { Thread thread = new Thread(mListener, MountListener.class.getName()); thread.start(); }
class MountListener 实现了Runnable接口,在它继承的run()方法中创建了一个无限循环:
- while (true) {
- listenToSocket();
- }
while (true) { listenToSocket(); }
|
在listenToSocket()方法中:
- socket = new LocalSocket();
- LocalSocketAddress address = new LocalSocketAddress(VOLD_SOCKET,
- LocalSocketAddress.Namespace.RESERVED);
- socket.connect(address);
- InputStream inputStream = socket.getInputStream();
- mOutputStream = socket.getOutputStream();
- ····································
- while (true) {
- int count = inputStream.read(buffer);
- if (count < 0) break;
- int start = 0;
- for (int i = 0; i < count; i++) {
- if (buffer[i] == 0) {
- String event = new String(buffer, start, i - start);
- handleEvent(event);
- start = i + 1;
- }
- }
- }
socket = new LocalSocket(); LocalSocketAddress address = new LocalSocketAddress(VOLD_SOCKET, LocalSocketAddress.Namespace.RESERVED); socket.connect(address); InputStream inputStream = socket.getInputStream(); mOutputStream = socket.getOutputStream(); ···································· while (true) { int count = inputStream.read(buffer); if (count < 0) break; int start = 0; for (int i = 0; i < count; i++) { if (buffer[i] == 0) { String event = new String(buffer, start, i - start); handleEvent(event); start = i + 1; } } }
|
首先,实例化一个本地的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)) {
- .........................
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通信
- ....................
- Intent intent = new Intent(Intent.ACTION_UMS_CONNECTED);
- mContext.sendBroadcast(intent);
- ....................
....................Intent intent = new Intent(Intent.ACTION_UMS_CONNECTED); mContext.sendBroadcast(intent); ....................
|
- if ((uevent_sock = socket(PF_NETLINK,
- SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
- ........
- }
- if (setsockopt(uevent_sock, SOL_SOCKET, SO_RCVBUFFORCE, &uevent_sz,
- sizeof(uevent_sz)) < 0) {
- .......
- }
- if (bind(uevent_sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
- ......
- }
if ((uevent_sock = socket(PF_NETLINK, SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {........ } if (setsockopt(uevent_sock, SOL_SOCKET, SO_RCVBUFFORCE, &uevent_sz, sizeof(uevent_sz)) < 0) {....... } if (bind(uevent_sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { ...... }
|
创建一个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;
- }
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; }
dipatch_uevent():根据uevent->subsystem确定uevent处理的句柄。
- struct uevent {
- const char *action;
- const char *path;
- const char *subsystem;
- const char *firmware;
- int major;
- int minor;
- };
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 *);
- };
struct uevent_dispatch { char *subsystem; int (* dispatch) (struct uevent *);};
- while(1) {
- ········
- FD_ZERO(&read_fds);
- FD_SET(door_sock, &read_fds);
- if (door_sock > max)
- max = door_sock;
- FD_SET(uevent_sock, &read_fds);
- if (uevent_sock > max)
- max = uevent_sock;
- if (fw_sock != -1) {
- FD_SET(fw_sock, &read_fds);
- if (fw_sock > max)
- max = fw_sock;
- }
-
- if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) {
- LOGE("select() failed (%s)", strerror(errno));
- sleep(1);
- continue;
- }
- if (!rc) {
- continue;
- }
-
- if (FD_ISSET(door_sock, &read_fds)) {
- struct sockaddr addr;
- socklen_t alen;
- alen = sizeof(addr);
- if (fw_sock != -1) {
- LOGE("Dropping duplicate framework connection");
- int tmp = accept(door_sock, &addr, &alen);
- close(tmp);
- continue;
- }
- if ((fw_sock = accept(door_sock, &addr, &alen)) < 0) {
- LOGE("Unable to accept framework connection (%s)",
- strerror(errno));
- }
- LOG_VOL("Accepted connection from framework");
-
- volmgr_usb_bootstrap();
- if ((rc = volmgr_send_states()) < 0) {
- LOGE("Unable to send volmgr status to framework (%d)", rc);
- }
- }
-
- if (FD_ISSET(fw_sock, &read_fds)) {
- if ((rc = process_framework_command(fw_sock)) < 0) {
- if (rc == -ECONNRESET) {
- LOGE("Framework disconnected");
- close(fw_sock);
- fw_sock = -1;
- } else {
- LOGE("Error processing framework command (%s)",
- strerror(errno));
- }
- }
- }
-
- if (FD_ISSET(uevent_sock, &read_fds)) {
- if ((rc = process_uevent_message(uevent_sock)) < 0) {
- LOGE("Error processing uevent msg (%s)", strerror(errno));
- }
- }
- }
while(1) { ········ FD_ZERO(&read_fds);//初始化文件描述集合 FD_SET(door_sock, &read_fds);//将door_sock加入文件描述集 if (door_sock > max) max = door_sock; FD_SET(uevent_sock, &read_fds);//将event_sock加入文件描述集 if (uevent_sock > max) max = uevent_sock; if (fw_sock != -1) { FD_SET(fw_sock, &read_fds);//将fw_sock加入文件描述集 if (fw_sock > max) max = fw_sock; } //当所有的文件描述符都没改变时,阻塞线程 if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) { LOGE("select() failed (%s)", strerror(errno)); sleep(1); continue; } if (!rc) { continue; } //检测如果是door_sock,检测与framework的连接,并发送msg if (FD_ISSET(door_sock, &read_fds)) { struct sockaddr addr; socklen_t alen; alen = sizeof(addr); if (fw_sock != -1) { LOGE("Dropping duplicate framework connection"); int tmp = accept(door_sock, &addr, &alen); close(tmp); continue; } if ((fw_sock = accept(door_sock, &addr, &alen)) < 0) { LOGE("Unable to accept framework connection (%s)", strerror(errno)); } LOG_VOL("Accepted connection from framework");/* for iNand */volmgr_usb_bootstrap(); if ((rc = volmgr_send_states()) < 0) { LOGE("Unable to send volmgr status to framework (%d)", rc); } } //如果是fw_sock,执行framework传来的命令 if (FD_ISSET(fw_sock, &read_fds)) { if ((rc = process_framework_command(fw_sock)) < 0) { if (rc == -ECONNRESET) { LOGE("Framework disconnected"); close(fw_sock); fw_sock = -1; } else { LOGE("Error processing framework command (%s)", strerror(errno)); } } } //如果是uevent_sock,产生一个uevent事件 if (FD_ISSET(uevent_sock, &read_fds)) { if ((rc = process_uevent_message(uevent_sock)) < 0) { LOGE("Error processing uevent msg (%s)", strerror(errno)); } } } // while
|
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();
http://blog.csdn.net/fengkehuan/article/details/6195049