看了很长时间Vold存储模块的相关知识,也深入的研究一段时间的Android源码,打算把自己看过的经验之贴、参考资料和自己的一些见解,以帖子的形式发出来,供有兴趣的同仁们参考,有不对的地方请指正,我们相互交流。
1.1 vold的原理与机制分析
1.1.1 Vold 架构
从上图中可知:
· Vold中的NetlinkManager模块接收来自Linux内核的uevent消息。例如SD卡的插拔等动作都会引起Kernel向NM发送uevent消息。
· NetlinkManager将这些消息转发给VolumeManager模块。VolumeManager会对应做一些操作,然后把相关信息通过CommandListener发送给MountService,MountService根据收到的消息会发送相关的处理命令给VolumeManager做进一步的处理。例如待SD卡插入后,VolumeManager会将来自NetlinkManager的“Disk Insert”消息发送给MountService,而后MountService则发送“Mount”指令给Vold,指示它挂载这个SD卡。
· CommandListener模块内部封装了一个Socket用于跨进程通信。它在Vold进程中属于监听端(即是服务端),而它的连接端(即客户端)则是MountService。它一方面接收来自MountService的控制命令(例如卸载存储卡、格式化存储卡等),另一方面VolumeManager和NetlinkManager模块又会通过它,将一些信息发送给MountService。
1.1.2初识Vold
下面来初步的认识Vold,代码在system\vold\main.cpp
int main() {
mkdir("/dev/block/vold", 0755); //创建一个目录/dev/block/vold
//创建一个VolumeManager对象,该对象为单例模式
if (!(vm = VolumeManager::Instance())) {
SLOGE("Unable to create VolumeManager");
exit(1);
};
//创建一个NetlinkManager对象,该对象为单例模式
if (!(nm = NetlinkManager::Instance())) {
SLOGE("Unable to create NetlinkManager");
exit(1);
};
//创建一个CommandListener对象
cl = new CommandListener();
vm->setBroadcaster((SocketListener *) cl);
nm->setBroadcaster((SocketListener *) cl);
//启动VolumeManager
if (vm->start()) {
SLOGE("Unable to start VolumeManager (%s)", strerror(errno));
exit(1);
}
//根据fstab配置文件初始化VolumeManager
if (process_config(vm)) {
SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno));
}
//启动NetlinkManager对象
if (nm->start()) {
SLOGE("Unable to start NetlinkManager (%s)", strerror(errno));
exit(1);
}
//通过往/sys/block目录下对应的uevent文件写“add\n”来触发内核发送Uevent消息
coldboot("/sys/block");
//启动CommandListener
if (cl->startListener()) {
SLOGE("Unable to start CommandListener (%s)", strerror(errno));
exit(1);
}
}
1.2 NetlinkManager模块的分析
1.2.1 NetlinkManager架构流程图
1.2.2 start的分析
int NetlinkManager::start() {
struct sockaddr_nl nladdr;
int sz = 64 * 1024;
int on = 1;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = getpid();
nladdr.nl_groups = 0xffffffff;
// 创建一个socket用于内核空间和用户空间的异步通信,监控系统的hotplug事件
if ((mSock = socket(PF_NETLINK,
SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
SLOGE("Unable to create uevent socket: %s", strerror(errno));
return -1;
}
if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {
SLOGE("Unable to set uevent socket SO_RECBUFFORCE option: %s", strerror(errno));
return -1;
}
if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno));
return -1;
}
if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
SLOGE("Unable to bind uevent socket: %s", strerror(errno));
return -1;
}
// 利用新创建的socket实例化一个NetlinkHandler类对象,NetlinkHandler继承了类NetlinkListener,
// NetlinkListener又继承了类SocketListener
mHandler = new NetlinkHandler(mSock);
if (mHandler->start()) { //启动NetlinkHandler
SLOGE("Unable to start NetlinkHandler: %s", strerror(errno));
return -1;
}
return 0;
}
NetlinkHandler构造
NetlinkHandler::NetlinkHandler(int listenerSocket) :
NetlinkListener(listenerSocket) {
}
继承父类
NetlinkListener::NetlinkListener(int socket) :
SocketListener(socket, false) {
mFormat = NETLINK_FORMAT_ASCII;
}
接着调用的start()函数,也是最终实现在SockListener的startListener()。
int NetlinkHandler::start() {
return this->startListener();
}
int SocketListener::startListener() {
if (!mSocketName && mSock == -1) {
SLOGE("Failed to start unbound listener");
errno = EINVAL;
return -1;
} else if (mSocketName) {
if ((mSock = android_get_control_socket(mSocketName)) < 0) {
SLOGE("Obtaining file descriptor socket '%s' failed: %s",
mSocketName, strerror(errno));
return -1;
}
}
if (mListen && listen(mSock, 4) < 0) {
SLOGE("Unable to listen on socket (%s)", strerror(errno));
return -1;
} else if (!mListen)
mClients->push_back(new SocketClient(mSock, false));
if (pipe(mCtrlPipe)) {
SLOGE("pipe failed (%s)", strerror(errno));
return -1;
}
if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
SLOGE("pthread_create (%s)", strerror(errno));
return -1;
}
return 0;
}
void *SocketListener::threadStart(void *obj) {
SocketListener *me = reinterpret_cast<SocketListener *>(obj);
me->runListener();