1 总体介绍
在Android 中,当SD卡插入系统之后,系统会自动挂载。Vold 就是负责挂载SD卡的,vold 的全称是volume daemon。实际上是负责完成系统的CDROM,USB 大容量存储,MMC 卡等扩展存储的挂载任务自动完成的守护进程。它提供的主要特点是支持这些存储外设的热插拔。
1.1总体流程图
Ø 绿色箭头:表示插入SD卡后事件传递以及SD卡挂载
Ø 红色箭头:表示挂载成功后的消息传递流程
Ø 黄色箭头:表示MountService发出挂载/卸载SD卡的命令
1.2总体类图
n main.cpp,vold的入口函数,系统起来会只执行vold的可执行文件,调到这个main函数中。
n NetlinkManager.cpp位于源码位置/system/vold/NetlinkManager.cpp。该类的主要通过引用NetlinkHandler类中的onEvent()方法来接收来自内核的事件消息,NetlinkHandler位于/system/vold/NetlinkHandler.cpp。
n VolumeManager:位于源码位置/system/vold/VolumeManager.cpp。该类的主要作用是接收经过NetlinkManager处理过后的事件消息。
n DirectVolume:位于/system/vold/DirectVolume.cpp。该类的是一个工具类,主要负责对传入的事件进行进一步的处理,block事件又可以分为:Add,Removed,Change,Noaction这四种。
n Volume:Volume.cpp位于/system/vold/Volume.cpp,该类是负责SD卡挂载的主要类。Volume.cpp主要负责检查SD卡格式,以及对复合要求的SD卡进行挂载,并通过Socket将消息SD卡挂载的消息传递给NativeDaemonConnector。
总的讲,vold程序需要分层三部分,第一部分为NetlinkManager,管理接受来自kernel的UEvent消息,第二部分为VolumeManager,主要负责处理来自NetlinkManager的消息和来自java层的消息,之后真正的挂载卸载动作就需要volume负责了。
2 初始化流程
2.1 时序图
2.2 代码分析
在Android 系统启动的时候,init进程会去解析init.rc文件,在该文件中,有如下代码:
service vold /system/bin/vold class core socket vold stream 0660 root mount ioprio be 2 |
定义了一个vold的service,去执行vold程序,并创建了一个名字为vold的socket,init进程解析完后就去执行vold程序,创建与java层通信的Socket。
在Android 源码/system/vold路径下的main.cpp,这个就是vold程序的入口,我们看看起main函数,代码如下:
int main() {
VolumeManager *vm;
CommandListener *cl;
NetlinkManager *nm;
if (!(vm = VolumeManager::Instance())) {//创建VolumeManager实例
};
if (!(nm = NetlinkManager::Instance())) {//创建NelinkManager实例
};
cl = new CommandListener(); //创建与java层socket通信的接口
vm->setBroadcaster((SocketListener *) cl);
nm->setBroadcaster((SocketListener *) cl);
if (vm->start()) { //什么都没做
}
if (process_config(vm)) {//初始化fstab
SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno));
}
if (nm->start()) {//开始监听kernel上报的vold消息
}
……
if (cl->startListener()) {//开始监听来自java层的socket消息
SLOGE("Unable to start CommandListener (%s)", strerror(errno));
exit(1);
}
while(1) {
sleep(1000);
}
exit(0);
}
首先,在
main
函数中,需要创建
VolumeManager
和
NetlinkManager
的实例,里面就做了一些初始化的动作,这里就不多说了。
接着,则是初始化vold与java层的socket通信接口。创建了的CommandListener实例。在上面的类图关系中,我们知道,CommandListener继承于FrameworkListener,而FrameworkListener有继承于SocketListener。先看看CommandListener的初始化代码:
CommandListener::CommandListener() :
FrameworkListener("vold") {
registerCmd(new DumpCmd());
registerCmd(new VolumeCmd()); //处理volume事件
registerCmd(new AsecCmd());
registerCmd(new ObbCmd());
registerCmd(new StorageCmd());
registerCmd(new XwarpCmd());
registerCmd(new CryptfsCmd());
}
在上面代码中我们看到,先以“
vold
”为参数构造
FrameworkListener
类,完成之后,则调用
FrameworkListener
类中的
registerCmd()
方法,注册一些处理方法类,而对于
sd
卡挂载的事件,我们先关注
VolumeCmd
类,它是
FrameworkListener
的内部类,用于处理
Volume
事件。接下来,看
FrameworkListener
的构造函数: