《android -- vold机制简要分析》由会员分享,可在线阅读,更多相关《android -- vold机制简要分析(27页珍藏版)》请在金锄头文库上搜索。
1、Android - Vold 机制简要分析Vold 是用于管理和控制 Android 外部存储介质的后台进程,这里说的管控,主要包括 SDK的插拔、挂载/卸载和格式化等;它是 Android 平台外部存储系统的管控枢纽。Vold 的整个控制模块主要由三个类模块构成:NetlinkManager、VolumeManager 和CommandListener,它们的功能划分大概是:NetlinkManager:用于从 kernel 中获取 SD 卡插拔的 Uevnet 消息VolumeManager:管理模块,对 NetlinkManager 转发的消息做一些处理,并通过CommandListen
2、er 发送给 framework(MountService.java) ;接着 framework 会通过套接字下发命令,指引 VolumeManager 对存储设备做下一步的操作,如挂载/卸载等CommandListener:通过 socket,实现 MountService.java 与 Vold 之间的消息交换NetLink 是 Linux 下用户进程和 kernel 进行信息交互的一种机制,借助这种机制,用户进程(如 Vold/Netd)可以接收来自 kernel 的一些消息,同时也可以向 kernel 发送一些控制命令。NetlinkManager 就是基于此设计的。 Uevent
3、也跟 Linux 系统有关,它与 Linux 的设备文件系统有一定关系;这里,我们可以简单的认为,Uevent 就是一个字符串,它描述了外部存储设备插入/拔出、挂载/卸载的状态信息。Vold 通过 Netlink 机制,可以得到这些信息,并进行外部存储设备的管理、控制。由上述介绍,我们可以得到如下的 Vold 框架图描述:有了 Vold 的架构描述,接下来就开始分析 Vold 进程的整体流程及实现了。一、Vold 进程的声明与创建Vold 进程的声明与创建过程跟 zygote 一样,在 init.rc 中声明,在 init 进程创建:java view plain copy 在 CODE 上查
4、看代码片派生到我的代码片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:s0 class core socket vold stream 0660 root mount socket cryptd stream 0660 root mount ioprio be 2 在创建 Vold 进程时,会为
5、它创建两个 socket,用于与 framework 进行信息交互。其他的细节,参考之前 zygote 进程创建的介绍。二、进入 Vold 主程序Vold 的主程序在/system/vold 目录中,直接看 main.cpp:main()函数:cpp view plain copy 在 CODE 上查看代码片派生到我的代码片int main(int argc, char* argv) setenv(ANDROID_LOG_TAGS, *:v, 1); android:base:InitLogging(argv, android:base:LogdLogger(android:base:SYST
6、EM); LOG(INFO) setDebug(true); /3、创建 CommandListener、CryptCommandListener cl = new CommandListener(); ccl = new CryptCommandListener(); vm-setBroadcaster(SocketListener *) cl); nm-setBroadcaster(SocketListener *) cl); /4、启动 VolumeManager if (vm-start() PLOG(ERROR) start() PLOG(ERROR) startListener()
7、 PLOG(ERROR) startListener() PLOG(ERROR) setBroadcaster(SocketListener *) cl)nm-start()现按步骤进行分析。1、NetlinkManager:Instance():cpp view plain copy 在 CODE 上查看代码片派生到我的代码片NetlinkManager *NetlinkManager:Instance() if (!sInstance) sInstance = new NetlinkManager(); return sInstance; NetlinkManager:NetlinkMan
8、ager() mBroadcaster = NULL; /type:SocketListener*,用来进行 socket 通信 这里使用了单例模式来构建 NetlinkManager 对象,构造函数中只是简单地初始化了成员变量。2、NetlinkManager:setBroadcaster():cpp view plain copy 在 CODE 上查看代码片派生到我的代码片cl = new CommandListener(); nm-setBroadcaster(SocketListener *) cl); void setBroadcaster(SocketListener *sl) m
9、Broadcaster = sl; setBroadcaster()函数也很简单,为 mBroadcast 进行赋值。3、NetlinkManager:start():cpp view plain copy 在 CODE 上查看代码片派生到我的代码片int NetlinkManager:start() struct sockaddr_nl nladdr; int sz = 64 * 1024; int on = 1; memset( nladdr.nl_family = AF_NETLINK; nladdr.nl_pid = getpid(); nladdr.nl_groups = 0xfff
10、fffff; /创建地址族为 PF_NETLINK 的 socket,与 Kernel 进行通信;也可以为 AF_NETLINK.参照 Linux Netlink 机制资料 if (mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT) start() /startListener 通过父类方法,在 mSock 上监听连接请求 SLOGE(Unable to start NetlinkHandler: %s, strerror(errno); goto out; return 0; out: c
11、lose(mSock); return -1; start()方法中创建了一个句柄值为 mSock 的套接字,用来和 kernel 通信;而实际具体的socket 信息交互是由 NetlinkHandler 处理的。NetlinkHandler 的实现有一套继承机制,其实际继承关系如图所示:按照继承关系,分析它的构建过程:cpp view plain copy 在 CODE 上查看代码片派生到我的代码片mHandler = new NetlinkHandler(mSock); NetlinkHandler:NetlinkHandler(int listenerSocket) : Netlink
12、Listener(listenerSocket) cpp view plain copy 在 CODE 上查看代码片派生到我的代码片/* temporary version until we can get Motorola to update their * ril.so. Their prebuilt ril.so is using this private class * so changing the NetlinkListener() constructor breaks their ril. */ NetlinkListener:NetlinkListener(int socket
13、) : SocketListener(socket, false) mFormat = NETLINK_FORMAT_ASCII; cpp view plain copy 在 CODE 上查看代码片派生到我的代码片SocketListener:SocketListener(const char *socketName, bool listen) init(socketName, -1, listen, false); void SocketListener:init(const char *socketName, int socketFd, bool listen, bool useCmdNu
14、m) mListen = listen;/是否是监听端,这里为 false mSocketName = socketName;/保存 socket 的名字 mSock = socketFd;/保存 socket 的句柄值,与 Kernel 通信 mUseCmdNum = useCmdNum; pthread_mutex_init( mClients = new SocketClientCollection();/集合对象,保存类型 SocketClient 为的变量;保存了 socket 通信中的客户端对象 再看 NetlinkHandler:start()方法:cpp view plain
15、copy 在 CODE 上查看代码片派生到我的代码片int NetlinkHandler:start() return this-startListener(); 实际调用的是 SocketListener:startListener():cpp view plain copy 在 CODE 上查看代码片派生到我的代码片int SocketListener:startListener() return startListener(4); int SocketListener:startListener(int backlog) if (!mSocketName & mSock = -1) SLOGE(Failed to start unbound listener); errno = EINVAL; return -1; else if (mSocketName) if (mSock = android_get_control_socket(mSocketName) push_back(new SocketClient(mSock, false, mUseCmdNum);/创建一个SocketClient