Android7.0 Vold 进程工作机制分析之整体流程
一、Vold简介
Vold是Volume Daemon的缩写,负责管理和控制Android平台外部存储设备,包括SD插拨、挂载、卸载、格式化等。它是通过init进程解析init.rc脚本所启动的进程.它处于Native层.
二、基础架构
这里引用Gityuan博客的一张图。
SystermServer进程和Vold进程是通过Socket进行通信的,Vold进程和Kernel是通过Netlink 进行通信的,Netlink 是一种特殊的Socket。
相关介绍:Netlink是linux提供的用于内核和用户态进程之间的通信方式,也能用于用户空间的两个进程通信,通过这个机制,位于用户空间的进程,可接收来自Kernel的一些信息(例如Vold中用到的USB或SD的插拔消息),同时应用层也可通过Netlink向Kernel发送一些控制命令。
先大体的简单介绍一下流程:
1.由SystemServer进程发起挂载/卸载请求
运行在SystemServer进程的MountService通过NativeDaemonConnector给CommandListener发送请求,CommandListener再通知VolumeManager进行实际操作
2.由Kernel发起挂载/卸载请求
Kernel通过Netlink发送请求(传递uevent)给NetlinkManager,NetlinkManager通过内部的线程NetlinkHandler交给VolumeManager进行实际操作,然后VolumeManager通过CommandListener通知MountService
在分别仔细介绍着两个流程之前,了解下Vold进程的启动流程,先把握整体流程再细化。
三、Vold进程启动流程
Vold进程代码路径:system/vold/
主要类的路径(方便查阅)
system/vold/目录下
main.cpp————————————system/vold/main.cpp
NetlinkManager.cpp———————–system/vold/NetlinkManager.cpp
NetlinkHandler.cpp————————system/vold/NetlinkHandler.cpp
VoldCommand.cpp————————system/vold/VoldCommand.cpp
VolumeBase.cpp—————————system/vold/VolumeBase.cpp
VolumeManager.cpp———————–system/vold/VolumeManager.cpp
system/core/libsysutils/src/目录下
SocketListener.cpp————————–system/core/libsysutils/src/SocketListener.cpp
NetlinkListener.cpp————————–system/core/libsysutils/src/NetlinkListener.cpp
FrameworkListener.cpp——————–system/core/libsysutils/src/FrameworkListener.cpp
FrameworkCommand.cpp——————system/core/libsysutils/src//FrameworkCommand.cpp
system/core/include/sysutils/目录下
对应着system/core/libsysutils/src/目录的h文件
贴上我绘制的时序图(缩放浏览器可以放大查看或者在新标签页打开)
分步骤给大家详细介绍下:
1.main()
Vold进程代码位于system/vold/目录下,从main.cpp开始,后续的截图我只截取主要的代码
在main方法里,主要做以下几件事情
①初始化VolumeManager ,CommandListener ,NetlinkManager 三个类的实例
②给VolumeManager 和NetlinkManager 设置CommandListener 实例,用作后续监听两个Socket,用得是设计模式中的Command(命令)模式
③启动VolumeManager ,CommandListener ,NetlinkManager
④解析Vold的配置文件fstab
⑤做一次冷启动
int main(int argc, char** argv) {
......
VolumeManager *vm;
CommandListener *cl;
NetlinkManager *nm;
//创建文件夹/dev/block/vold
mkdir("/dev/block/vold", 0755);
//用于cryptfs检查,并mount加密的文件系统
klog_set_level(6);
//获取VolumeManager的单例
if (!(vm = VolumeManager::Instance())) {
LOG(ERROR) << "Unable to create VolumeManager";
exit(1);
}
//获取NetlinkManager的单例
if (!(nm = NetlinkManager::Instance())) {
LOG(ERROR) << "Unable to create NetlinkManager";
exit(1);
}
//实例化
cl = new CommandListener();
//设置socket监听对象
vm->setBroadcaster((SocketListener *) cl);
nm->setBroadcaster((SocketListener *) cl);
//启动VolumeManager
if (vm->start()) {
PLOG(ERROR) << "Unable to start VolumeManager";
exit(1);
}
//解析Vold的配置文件fstab,初始化VolumeManager
if (process_config(vm)) {
PLOG(ERROR) << "Error reading configuration... continuing anyways";
}
//启动NetlinkManager
if (nm->start()) {
PLOG(ERROR) << "Unable to start NetlinkManager";
exit(1);
}
// 冷启动,vold错过了一些uevent,重新触发。向/sys/block的uevent文件写入”add\n” 字符触发内核发送Uevent消息,相当执行了一次热插拔。
coldboot("/sys/block");
//启动CommandListener
if (cl->startListener()) {
PLOG(ERROR) << "Unable to start CommandListener";
exit(1);
}
......
}
第④步
如果vold.fstab解析无误,VolueManager将创建具体的Volume,若vold.fstab解析不存在或者打开失败,Vold将会读取Linux内核中的参数,此时如果参数中存在SDCARD(也就是SD的默认路径),VolumeManager则会创建AutoVolume,如果不存在这个默认路径那么就不会创建。
它的格式对应如下:
type———————–挂载命令
lable———————–标签
mount_point ————挂载点
part ———————–第几个分区
sysfs_path—————设备的sysfs paths
sysfs_path可以有多个 part指定分区个数,如果是auto没有分区
第⑤步
coldboot方法会调用do_coldboot方法,往/sys/block目录写入add\n事件。
static