ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
Vold使用CL模块的流程是: · 使用new创建一个CommandListener对象; · 调用CL的startListener函数。 来看这两个函数。 1. 创建CommandListener的分析 和NetlinkerHandler一样,CommandListener也有一个相对不简单的派生关系,它的家族图谱如图9-5所示: :-: ![](http://img.blog.csdn.net/20150802164411883?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 图9-5 CommandListener家族图谱 根据上图可以知道: - CL定义了一些和Command相关的内部类,这里采用了设计模式中的Command模式,每个命令的处理函数都是runCommand。注意,上图只列出了部分Command类。 - CL也是从SocketListener派生的,不过它是Socket的监听(listen)端。 下面看它的代码: **CommandListener.cpp** ~~~ CommandListener::CommandListener() : FrameworkListener("vold") { //CL模块支持的命令 registerCmd(new DumpCmd()); registerCmd(new VolumeCmd()); registerCmd(new AsecCmd()); registerCmd(new ShareCmd()); registerCmd(new StorageCmd()); registerCmd(new XwarpCmd()); } /* registerCmd函数将Command保存到mCommands中,mCommands的定义为一个列表,如下: typedef android::List<FrameworkCommand *>FrameworkCommandCollection; */ voidFrameworkListener::registerCmd(FrameworkCommand *cmd) { mCommands->push_back(cmd); } ~~~ 从上面的代码可知,CommandListener的基类是FrameworkListener,而FrameworkListener又从SocketListener类派生。之前在分析NM模块的NetLinkerHandler时,已介绍过SocketListener相关的知识了,所以此处不再赘述,只总结一下CL创建后的结果,它们是: - CL会创建一个监听端的socket,这样就可以接收客户端的链接。 - 客户端发送命令给CL,CL则从mCommands中找到对应的命令,并交给该命令的runCommand函数处理。 下面来关注第二个函数startListener,这个函数由SocketListener实现。 2. startListener的分析和数据处理 其实在分析NetlinkerHandler时,已经介绍了startListener函数,这里再简单回顾一下,有些具体内容和本章对NetlinkerHandler的分析有关。 **SocketListener.cpp** ~~~ int SocketListener::startListener() { if(!mSocketName && mSock == -1) { ...... errno = EINVAL; return -1; } else if (mSocketName) { //mSOcketName为字符串“vold”。android_get_control_socket函数返回 //对应的socket句柄 if((mSock = android_get_control_socket(mSocketName)) < 0) { ...... return -1; } } //CL模块是监听端 if(mListen && listen(mSock, 4) < 0) { ...... return -1; } elseif (!mListen) mClients->push_back(new SocketClient(mSock)); if(pipe(mCtrlPipe)) { ...... return -1; } //创建工作线程threadStart if(pthread_create(&mThread, NULL, SocketListener::threadStart, this)) { return -1; } return0; } ~~~ 当CL收到数据时,会调用onDataAvailable函数,它由FrameworkListener实现。 **FrameworkListener.cpp** ~~~ boolFrameworkListener::onDataAvailable(SocketClient *c) { charbuffer[255]; intlen; //读取数据 if((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) { ...... return errno; } elseif (!len) return false; intoffset = 0; int i; for (i= 0; i < len; i++) { if(buffer[i] == '\0') { //分发命令,最终会调用对应命令对象的runCommand进行函数处理。 dispatchCommand(c, buffer + offset); offset = i + 1; } } returntrue; } ~~~ dispatchCommand最终会根据收到的命令名(如“Volume”,“Share”等)来调用对应的命令对象(如VolumeCmd,ShareCmd)的runCommand函数以处理请求。这一块非常简单,这里就不再详述了。 3. CL模块的总结 CL模块的主要工作是: - 建立一个监听端的socket。 - 接收客户端的连接和请求,并调用对应Command对象的runComand函数处理。 目前,CL模块唯一的客户端就是MountService。来看看它。