一、Vold工作机制
Vold是Volume Daemon的缩写,它是Android平台中外部存储系统的管控中心,是管理和控制Android平台外部存储设备的后台进程。其功能主要包括:SD卡的插拔事件检测、SD卡挂载、卸载、格式化等。
如上图所示,Vold中的NetlinkManager模块接收来自Linux Kernel的uevent消息。
NetlinkManager将这些消息转发给VolumeManager模块。VolumeManager会对应做一些操作,然后把相关信息通过CommandListener发送给MountService。
MountService根据收到的消息后,根据情况会利用CommandListener发送相关的处理命令给VolumeManager做进一步处理。
CommandListener模块内部封装了一个Socket用于跨进程通信。它一方面接收来自MountService的控制命令,另一方面VolumeManager通过它将消息发送给MountService。
Tips:
Netlink是Linux系统中用户空间进程和Kernel进行通信的一种机制,是基于Socket的异步通信机制。
通过这种机制,位于用户空间的进程可以接收来自Kernel的一些信息,同时用户空间进程也可以利用Netlink向Kernel发送一些控制命令。
--从8.0开始框架层的MountService已经被StorageMangerService替换了。
二、Vold进程启动过程
service vold /system/bin/vold \--blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \--fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0class coresocket vold stream 0660 root mountsocket cryptd stream 0660 root mountioprio be 2writepid /dev/cpuset/foreground/tasksshutdown critical
vold和cryptd两个socket通道
被init进程启动后,将调用system/vold/main.cpp中的main函数:
int main(int argc, char** argv) {setenv("ANDROID_LOG_TAGS", "*:v", 1);android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));LOG(INFO) << "Vold 3.0 (the awakening) firing up";LOG(VERBOSE) << "Detected support for:"<< (android::vold::IsFilesystemSupported("ext4") ? " ext4" : "")<< (android::vold::IsFilesystemSupported("f2fs") ? " f2fs" : "")<< (android::vold::IsFilesystemSupported("vfat") ? " vfat" : "");VolumeManager *vm;CommandListener *cl;CryptCommandListener *ccl;NetlinkManager *nm;parse_args(argc, argv);sehandle = selinux_android_file_context_handle();if (sehandle) {selinux_android_set_sehandle(sehandle);}// Quickly throw a CLOEXEC on the socket we just inherited from initfcntl(android_get_control_socket("vold"), F_SETFD, FD_CLOEXEC);fcntl(android_get_control_socket("cryptd"), F_SETFD, FD_CLOEXEC);mkdir("/dev/block/vold", 0755);/* For when cryptfs checks and mounts an encrypted filesystem */klog_set_level(6);/* Create our singleton managers */if (!(vm = VolumeManager::Instance())) {LOG(ERROR) << "Unable to create VolumeManager";exit(1);}if (!(nm = NetlinkManager::Instance())) {LOG(ERROR) << "Unable to create NetlinkManager";exit(1);}if (property_get_bool("vold.debug", false)) {vm->setDebug(true);}cl = new CommandListener();ccl = new CryptCommandListener();vm->setBroadcaster((SocketListener *) cl);nm->setBroadcaster((SocketListener *) cl);if (vm->start()) {PLOG(ERROR) << "Unable to start VolumeManager";exit(1);}bool has_adoptable;bool has_quota;if (process_config(vm, &has_adoptable, &has_quota)) {PLOG(ERROR) << "Error reading configuration... continuing anyways";}if (nm->start()) {PLOG(ERROR) << "Unable to start NetlinkManager";exit(1);}/** Now that we're up, we can respond to commands*/if (cl->startListener()) {PLOG(ERROR) << "Unable to start CommandListener";exit(1);}if (ccl->startListener()) {PLOG(ERROR) << "Unable to start CryptCommandListener";exit(1);}// This call should go after listeners are started to avoid// a deadlock between vold and init (see b/34278978 for details)property_set("vold.has_adoptable", has_adoptable ? "1" : "0");property_set("vold.has_quota", has_quota ? "1" : "0");// Do coldboot here so it won't block booting,// also the cold boot is needed in case we have flash drive// connected before Vold launchedcoldboot("/sys/block");// Eventually we'll become the monitoring threadwhile(1) {pause();}LOG(ERROR) << "Vold exiting";exit(0);
}
从上面的代码不难看出,Vold进程的main函数中,创建并启动其子模块VolumeManager、NetlinkManager和CommandListener后,就不再执行实际的工作了。
以后Vold进程具体的工作就会交付给子模块进行处理。