vold处理完磁盘事件,就要开始接受framework的操作命令,在main函数里面,开启了一个线程来监听framework的信息,当收到操作命令,vold进行解析,分析出命令,然后调用相应的磁盘操作函数,待操作完成后,再将操作结果的状态值反馈给framework,中间均使用了广播机制,使用了UDP协议。
在main函数中,有以下函数的调用:
-
if(cl->startListener()){
-
SLOGE("UnabletostartCommandListener(%s)",strerror(errno));
-
exit(1);
-
}
cl是CommandListener类实例化的一个对象,该对象专门负责与framework的通信,首先说明与CommandListener类相关的一些继承关系。CommandListener --> FrameworkListener --> SocketListener(父类)在CommandListener类中,声明了6个类,这6个类继承了VoldCommand类,VoldCommand类继承了FrameworkCommand,关系如下:VoldCommand --> FrameworkCommand(父类)以下是CommandListener类的声明:
-
classCommandListener:publicFrameworkListener{
-
public:
-
CommandListener();
-
virtual~CommandListener(){}
-
-
private:
-
staticvoiddumpArgs(intargc,char**argv,intargObscure);
-
-
classDumpCmd:publicVoldCommand{
-
public:
-
DumpCmd();
-
virtual~DumpCmd(){}
-
intrunCommand(SocketClient*c,intargc,char**argv);
-
};
-
-
classVolumeCmd:publicVoldCommand{
-
public:
-
VolumeCmd();
-
virtual~VolumeCmd(){}
-
intrunCommand(SocketClient*c,intargc,char**argv);
-
};
-
-
classShareCmd:publicVoldCommand{
-
public:
-
ShareCmd();
-
virtual~ShareCmd(){}
-
intrunCommand(SocketClient*c,intargc,char**argv);
-
};
-
-
classAsecCmd:publicVoldCommand{
-
public:
-
AsecCmd();
-
virtual~AsecCmd(){}
-
intrunCommand(SocketClient*c,intargc,char**argv);
-
};
-
-
classStorageCmd:publicVoldCommand{
-
public:
-
StorageCmd();
-
virtual~StorageCmd(){}
-
intrunCommand(SocketClient*c,intargc,char**argv);
-
};
-
-
classXwarpCmd:publicVoldCommand{
-
public:
-
XwarpCmd();
-
virtual~XwarpCmd(){}
-
intrunCommand(SocketClient*c,intargc,char**argv);
-
};
-
};
在这个类中,VoldCommand主要写了一个纯虚函数runCommand,声明如下:virtual int runCommand(SocketClient *c, int argc, char **argv) = 0;为了就是在CommandListener类中的实现,这里总共实现了6个版本的runCommand函数,下一篇文章只讨论其中一个比较重要的VolumeCmd类的实现,其余的跟这个类的实现差不多。开始深入startListener线程:进入startListener函数,创建了以下线程:
-
if(pthread_create(&mThread,NULL,SocketListener::threadStart,this)){
-
SLOGE("pthread_create(%s)",strerror(errno));
-
return-1;
-
}
这里跟前几章线程的创建几乎一样,
-
void*SocketListener::threadStart(void*obj){
-
SocketListener*me=reinterpret_cast<SocketListener*>(obj);
-
-
me->runListener();
-
pthread_exit(NULL);
-
returnNULL;
-
}
线程真正实现的函数在这里:
-
voidSocketListener::runListener(){
-
while(1){
-
SocketClientCollection::iteratorit;
-
fd_setread_fds;
-
intrc=0;
-
intmax=0;
-
-
FD_ZERO(&read_fds);
-
-
if(mListen){
-
max=mSock;
-
FD_SET(mSock,&read_fds);
-
}
-
-
FD_SET(mCtrlPipe[0],&read_fds);
-
if(mCtrlPipe[0]>max)
-
max=mCtrlPipe[0];
-
-
pthread_mutex_lock(&mClientsLock);
-
for(it=mClients->begin();it!=mClients->end();++it){
-
FD_SET((*it)->getSocket(),&read_fds);
-
if((*it)->getSocket()>max)
-
max=(*it)->getSocket();
-
}
-
pthread_mutex_unlock(&mClientsLock);
-
-
if((rc=select(max+1,&read_fds,NULL,NULL,NULL))<0){
-
SLOGE("selectfailed(%s)",strerror(errno));
-
sleep(1);
-
continue;
-
}elseif(!rc)
-
continue;
-
-
if(FD_ISSET(mCtrlPipe[0],&read_fds))
-
break;
-
if(mListen&&FD_ISSET(mSock,&read_fds)){
-
structsockaddraddr;
-
socklen_talen=sizeof(addr);
-
intc;
-
-
if((c=accept(mSock,&addr,&alen))<0){
-
SLOGE("acceptfailed(%s)",strerror(errno));
-
sleep(1);
-
continue;
-
}
-
pthread_mutex_lock(&mClientsLock);
-
mClients->push_back(newSocketClient(c));
-
pthread_mutex_unlock(&mClientsLock);
-
}
-
-
do{
-
pthread_mutex_lock(&mClientsLock);
-
for(it=mClients->begin();it!=mClients->end();++it){
-
intfd=(*it)->getSocket();
-
if(FD_ISSET(fd,&read_fds)){
-
pthread_mutex_unlock(&mClientsLock);
-
-
if(!onDataAvailable(*it)){
-
close(fd);
-
pthread_mutex_lock(&mClientsLock);
-
delete*it;
-
it=mClients->erase(it);
-
pthread_mutex_unlock(&mClientsLock);
-
}
-
FD_CLR(fd,&read_fds);
-
continue;
-
}
-
}
-
pthread_mutex_unlock(&mClientsLock);
-
}while(0);
-
}
-
}
将收到的命令交给onDataAvailable函数来处理,onDataAvailable函数是类的纯虚函数,在FrameworkListener类实现了该函数:
-
boolFrameworkListener::onDataAvailable(SocketClient*c){
-
charbuffer[255];
-
intlen;
-
-
if((len=read(c->getSocket(),buffer,sizeof(buffer)-1))<0){
-
SLOGE("read()failed(%s)",strerror(errno));
-
returnerrno;
-
}elseif(!len)
-
returnfalse;
-
-
intoffset=0;
-
inti;
-
-
for(i=0;i<len;i++){
-
if(buffer[i]=='\0'){
-
-
dispatchCommand(c,buffer+offset);
-
offset=i+1;
-
}
-
}
-
returntrue;
-
}
dispatchCommand函数用来选择不同的分支函数,因为在类有6个分支的实现版本,包括DumpCmd,VolumeCmd,ShareCmd,AsecCmd,StorageCmd和XwarpCmd。以下是dispatchCommand函数的源码:
-
voidFrameworkListener::dispatchCommand(SocketClient*cli,char*data){
-
FrameworkCommandCollection::iteratori;
-
intargc=0;
-
-
-
char*argv[FrameworkListener::CMD_ARGS_MAX];
-
-
-
-
-
-
-
-
for(i=mCommands->begin();i!=mCommands->end();++i){
-
FrameworkCommand*c=*i;
-
-
-
if(!strcmp(argv[0],c->getCommand())){
-
if(c->runCommand(cli,argc,argv)){
-
SLOGW("Handler'%s'error(%s)",c->getCommand(),strerror(errno));
-
}
-
gotoout;
-
}
-
}
-
-
cli->sendMsg(500,"Commandnotrecognized",false);
-
out:
-
intj;
-
for(j=0;j<argc;j++)
-
free(argv[j]);
-
return;
-
}
这里从代码可能有点疑问,这个循环为什么可以选择不同的分支新实现的函数呢?仔细看下代码会发现,在FrameworkListener中有一个注册函数,将新的派生类的名字注册到mCommands容器中,每个类的mCommand参数各代表一个派生类的名字。
-
voidFrameworkListener::registerCmd(FrameworkCommand*cmd){
-
mCommands->push_back(cmd);
-
}
在CommandListener类的构造函数中,分别对6个分支的派生类进行了注册,每次注册都实例化了一个新的对象存放到mCommands容器中。
-
CommandListener::CommandListener():
-
FrameworkListener("vold"){
-
registerCmd(newDumpCmd());
-
registerCmd(newVolumeCmd());
-
registerCmd(newAsecCmd());
-
registerCmd(newShareCmd());
-
registerCmd(newStorageCmd());
-
registerCmd(newXwarpCmd());
-
}
那这6个派生类的名称保存在FrameworkCommand类的一个私有变量mCommand中,该类的构造函数就是给mCommand赋值,源码:
-
FrameworkCommand::FrameworkCommand(constchar*cmd){
-
mCommand=cmd;
-
}
在刚才的FrameworkListener::dispatchCommand函数里,有这么一个比较:
-
if(!strcmp(argv[0],c->getCommand())){}
getCommand函数的源码:
-
constchar*getCommand(){returnmCommand;}
这里来看mCommand的赋值,我们知道以下关系:
DumpCmd --> VoldCommand --> FrameworkCommand
VolumeCmd --> VoldCommand --> FrameworkCommand
ShareCmd --> VoldCommand --> FrameworkCommand
AsecCmd --> VoldCommand --> FrameworkCommand
StorageCmd --> VoldCommand --> FrameworkCommand
XwarpCmd --> VoldCommand --> FrameworkCommand
所以在CommandListener类中的6个派生类中的构造函数中,必须初始化const char *cmd这个参数,以下是初始化代码:
-
CommandListener::DumpCmd::DumpCmd():
-
VoldCommand("dump"){
-
}
-
CommandListener::VolumeCmd::VolumeCmd():
-
VoldCommand("volume"){
-
}
-
CommandListener::ShareCmd::ShareCmd():
-
VoldCommand("share"){
-
}
-
CommandListener::StorageCmd::StorageCmd():
-
VoldCommand("storage"){
-
}
-
CommandListener::AsecCmd::AsecCmd():
-
VoldCommand("asec"){
-
}
-
CommandListener::XwarpCmd::XwarpCmd():
-
VoldCommand("xwarp"){
-
}
6个构造函数均初始化不同的cmd参数,分别为dump,volume,share,storage,asec,xwarp。在VoldCommand类的构造函数中,将cmd的值初始化FrameworkCommand类的构造函数。
-
VoldCommand::VoldCommand(constchar*cmd):
-
FrameworkCommand(cmd){
-
}
所以这个比较,就是将framework发下来的命令的第一个参数与mCommands容器中的6个对象的mCommand参数进行了比较,从而选择正确的处理分支函数。
分享到:
相关推荐
Android-vold源码分析
android-vold架构[收集].pdf
android中vold代码分析,主要用来自动挂载设备
android系统vold透析 Vold的全称是 Volume Daemon
在Android 系统中所有的热插拔设备都是通过Vold 进程挂载的。通过kernel–>vold–>StorageManagerService这样的架构去逐级上报热插拔事件。 一、Vold 入口 --> /system/vold/main.c int main(int argc, char** ...
USB之android_Vold分析.pdf
此篇文章详细描述了USB之android_Vold_分析
android中VOLD代码框架的讲解和分析,设计到存储管理
主要目录 1 Vold简介 2 Vold功能介绍 3 Vold通信 4 USB Storage Framework结构分析
USB之android_Vold分析,分析了linux udev与android vold的关系由来,vold的功能、架构,使用netlink的通信过程。kernel的uevent发送,framework层的处理、磁盘的挂载等等。
Android系统启动过程分析 本文主要介绍Android系统的启动过程,以Androidinit进程之后部分为主,init之前部分同标准Linux内核启动完全相同。于Android启动过程复杂,涉及C、C++及java部分内容,本文以流程分析为主线...
android平台移植ntfs-3g使支持ntfs格式tf卡、U盘、stat硬盘挂载,解压文件到external目录下,mm编译成功后,可手动指行 ntfs-3g /dev/block/vold/* /storage/sdcard1 或者添加 Ntfs.cpp Ntfs.h到system/vold目录实现...
本文档详细地介绍了android系统挂载中的vold,对vold的由来、功能、内部架构以及通信等方面进行了较为详细的介绍与较为深入的分析,是学习android挂载方面知识的一份比较好的材料。
android系统vold架构与流程透析
解析android中Vold进程,让大家更好更快的掌握Vold
Android vold 多U盘多分区挂载实现 可以对比原生的vold代码查看修改
Uevent 简介 NetLink 简介 MountService 功能介绍: MountService 同 StroageManager 的交互 MountService 同 Vold 的交互
android 对插入设备后产生的反应,诉说连接的响应与挂载