vold处理完磁盘事件,就要开始接受framework的操作命令,在main函数里面,开启了一个线程来监听framework的信息,当收到操作命令,vold进行解析,分析出命令,然后调用相应的磁盘操作函数,待操作完成后,再将操作结果的状态值反馈给framework,中间均使用了广播机制,使用了UDP协议。
cl是CommandListener类实例化的一个对象,该对象专门负责与framework的通信,首先说明与CommandListener类相关的一些继承关系。
CommandListener --> FrameworkListener --> SocketListener(父类)
在CommandListener类中,声明了6个类,这6个类继承了VoldCommand类,VoldCommand类继承了FrameworkCommand,关系如下:
VoldCommand --> FrameworkCommand(父类)
以下是CommandListener类的声明:
在这个类中,VoldCommand主要写了一个纯虚函数runCommand,声明如下:
virtual int runCommand(SocketClient *c, int argc, char **argv) = 0;
为了就是在CommandListener类中的实现,这里总共实现了6个版本的runCommand函数,下一篇文章只讨论其中一个比较重要的VolumeCmd类的实现,其余的跟这个类的实现差不多。
开始深入startListener线程:
进入startListener函数,创建了以下线程:
这里跟前几章线程的创建几乎一样,
线程真正实现的函数在这里:
将收到的命令交给onDataAvailable函数来处理,onDataAvailable函数是类的纯虚函数,在FrameworkListener类实现了该函数:
dispatchCommand函数用来选择不同的分支函数,因为在类有6个分支的实现版本,包括DumpCmd,VolumeCmd,ShareCmd,AsecCmd,StorageCmd和XwarpCmd。以下是dispatchCommand函数的源码:
这里从代码可能有点疑问,这个循环为什么可以选择不同的分支新实现的函数呢?
仔细看下代码会发现,在FrameworkListener中有一个注册函数,将新的派生类的名字注册到mCommands容器中,每个类的mCommand参数各代表一个派生类的名字。
在CommandListener类的构造函数中,分别对6个分支的派生类进行了注册,每次注册都实例化了一个新的对象存放到mCommands容器中。
那这6个派生类的名称保存在FrameworkCommand类的一个私有变量mCommand中,该类的构造函数就是给mCommand赋值,源码:
在刚才的FrameworkListener::dispatchCommand函数里,有这么一个比较:
getCommand函数的源码:
6个构造函数均初始化不同的cmd参数,分别为dump,volume,share,storage,asec,xwarp。
在VoldCommand类的构造函数中,将cmd的值初始化FrameworkCommand类的构造函数。
在main函数中,有以下函数的调用:
- if(cl->startListener()){
- SLOGE("UnabletostartCommandListener(%s)",strerror(errno));
- exit(1);
- }
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);
- };
- };
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);
- /*当收到framework的操作命令,执行该函数*/
- 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);
- }
- }
- 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;
- }
- voidFrameworkListener::dispatchCommand(SocketClient*cli,char*data){
- FrameworkCommandCollection::iteratori;
- intargc=0;
- /*staticconstintCMD_ARGS_MAX=16;
- 说明framework发送的命令最多只能容纳16个子串*/
- char*argv[FrameworkListener::CMD_ARGS_MAX];
- /*中间省略了字符串的处理部分,将每个子串保存到了argv数组中,
- 所以在out标记的位置,对argv[i]的数组进行释放,
- 因为使用了strdup函数复制字符串*/
- /*下面这个循环用来循环选择不同的分支实现函数,
- mCommands容器保存着6个新声明的类对象*/
- for(i=mCommands->begin();i!=mCommands->end();++i){
- FrameworkCommand*c=*i;
- /*当第一个参数与FrameworkCommand类中的mCommand参数相等时,
- 才去调用该对象新实现的runCommand函数*/
- 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::CommandListener():
- FrameworkListener("vold"){
- registerCmd(newDumpCmd());
- registerCmd(newVolumeCmd());
- registerCmd(newAsecCmd());
- registerCmd(newShareCmd());
- registerCmd(newStorageCmd());
- registerCmd(newXwarpCmd());
- }
- FrameworkCommand::FrameworkCommand(constchar*cmd){
- mCommand=cmd;
- }
- if(!strcmp(argv[0],c->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参数进行了比较,从而选择正确的处理分支函数。