一、vold简介:
vold进程接收来自内核的外部设备消息,用于管理和控制Android平台外部存储设备,包括SD插拨、挂载、卸载、格式化等;当外部设备发生变化时,内核通过Netlink发送uEvent格式的消息给用户空间程序,Netlink 是一种基于异步通信机制,在内核与用户应用间进行双向数据传输的特殊 socket,用户态应用使用标准的socket API 就可以使用 netlink 提供的强大功能。
Vold主要由三个模块组成:NetlinkManager、VolumeManager和CommandListener,其中三者的的关系如下图所示:
Vold是native程序,用于管理和控制Android平台外部存储设备的管控中心,是一个后台运行的进程。它与Java层的MountService交互,Vold接收来自kernel的uevent消息,然后向上层转发,MountService接收来自vold的消息,同时也可以向vold发送控制命令。
NetlinkManager模块专门接收来自Linux内核uevent消息,并将消息转发给VolumeManager处理,VolumeManager模块接着又把相关信息通过CommandListener发送给MountService,MountService根据收到的消息会发送相应的处理命令给VolumeManager,VolumeManager接收到命令后直接对外部存储设备进行操作。
CommandListener模块内部封装一个Socket用于跨进程通信,Java层的客户端MountService就是通过该Socket和服务端Vold进行通信的。
总结如下:
Linux Kernel:通过uevent向Vold的NetlinkManager发送Uevent事件;
NetlinkManager:接收来自Kernel的Uevent事件,再转发给VolumeManager;
VolumeManager:接收来自NetlinkManager的事件,再转发给CommandListener进行处理;
CommandListener:接收来自VolumeManager的事件,通过socket通信方式发送给MountService;
MountService:接收来自CommandListener的事件。
涉及的主要文件:
Framework层主要看MountService.java和NativeDaemonConnector.java;
Native层主要看NetlinkManager.cpp, NetlinkHandler.cpp, VolumeManager.cpp,CommandListener.cpp
二、Vold的启动流程
1、Vold的主程序在/system/vold/main.cpp目录中,直接看main.cpp::main()函数:
int main(int argc, char** argv) {
VolumeManager *vm;
CommandListener *cl;
CryptCommandListener *ccl;
NetlinkManager *nm;
//解析vold.rc中定义的blkid和fsck相关的参数
parse_args(argc, argv);
//获取external/sepolicy/file_contexts中的权限
sehandle = selinux_android_file_context_handle();
// Quickly throw a CLOEXEC on the socket we just inherited from init
//拿到init进程创建的名为vold的socket进程,并为它设置FD_CLOEXEC标志位
fcntl(android_get_control_socket("vold"), F_SETFD, FD_CLOEXEC);
fcntl(android_get_control_socket("cryptd"), F_SETFD, FD_CLOEXEC);
//创建vold目录,用于存放所有subdisk和sdcard的挂载点信息
mkdir("/dev/block/vold", 0755);
//1.创建VolumeManager
(vm = VolumeManager::Instance();
//2.创建NetlinkManager
nm = NetlinkManager::Instance();
//3.创建CommandListener和CryptCommandListener
cl = new CommandListener();
ccl = new CryptCommandListener();
vm->setBroadcaster((SocketListener *) cl);
nm->setBroadcaster((SocketListener *) cl);
//4.启动VolumeManager
vm->start();
//根据配置文件fstab.mt6735初始化VolumeManager
process_config(vm);
//5.启动NetlinkManager,处理来自kernel的usb/sdcard插拔消息
nm->start()
//6.应用层往/sys/block目录下的uevent文件写"add\n"指令,
//触发kernel向上发送Uevent消息,获取设备的当前信息
coldboot_sent_uevent_count_only = true;
coldboot("/sys/block");
coldboot_sent_uevent_count_only = false;
coldboot("/sys/block");
get_is_nvram_in_data();
//7.启动CommandListener
cl->startListener();
//8.启动CryptCommandListener
ccl->startListener();
exit(0);
}
2、NetlinkManager分析
(1)在主程序中,NetlinkManager主要做了以下三项工作:
a.构造NetlinkManager实例:nm = NetlinkManager::Instance();
b.设置广播监听事件:nm->setBroadcaster((SocketListener *) cl);
c.启动NetlinkManager:nm->start();
下面详细分析:
(2)构造构造NetlinkManager实例
NetlinkManager *NetlinkManager::Instance() {
if (!sInstance)
//采用单例模式来创建NetlinkManager实例
sInstance = new NetlinkManager();
return sInstance;
}
NetlinkManager::NetlinkManager() {
mBroadcaster = NULL;//初始化mBroadcaster&