Android 4.1 Netd详细分…

来源:互联网 发布:centos7 git 源码安装 编辑:程序博客网 时间:2024/06/02 21:18

上一篇我们按照函数的调用流程,完成了由NetlinkManager,NetlinkHandler,NetlinkListener,SocketListener组成的,从kernel到framework的单项消息通路。主要是通过内部的socket实现的通信。通过设置socket监听过滤属性,来接收kernel发出的event,(其中kernel发出的event部分不用了解,可以理解为是自发的)。并通过对于公共库的函数SocketListener的继承,函数重写。实现事件分析,并传递给framework层。

       接下来我们来实现,从framework层主动下发的以netd为终点的,以操作物理接口基本属性为目的的命令,

             接下来回到主函数部分,我们先越过DnsProxyListener,MDnsSdListener因为两部分为两个完全独立的部分,他们自身便可满足自己功能上需要的全部上下层通信,而 NetlinkManager需要与CommandListener 相结合才能实现相关功能,两部分是不可分割的。

      接下来,代码到达 cl 部分,该部分主要实习了同 Framework 层建立双向的联系,不但要接受来自Framework的功能命令,也要向 Framework 回复相应的处理结果和 kernel 状态,向 Framework层注册可用命令等等。两个层之间同样是通过 socket 通信。

[cpp] viewplaincopy
  1.  
  2.             dispatchCommand(c, buffer offset);  
  3.             offset 1;  
  4.          
  5.      
  6.     return true 
  7.  

       dispathCommand 函数直接按照字符串格式解析,因为命令源为 framework层的NetworkManagerService 通过调用 NativeDaemonConnector 里面的的 doCommand函数下发字符串命令,例如 mConnector.doCommand("tether interface add_upstream "+ iface);后面会详细介绍命令的源头 。

[cpp] viewplaincopy
  1. void FrameworkListener::dispatchCommand(SocketClient *cli, char *data)  
  2.     FrameworkCommandCollection::iterator i;  
  3.     int argc 0;  
  4.     char *argv[FrameworkListener::CMD_ARGS_MAX];  
  5.     char tmp[255];  
  6.     char *p data;  
  7.     char *q tmp;  
  8.     char *qlimit tmp sizeof(tmp) 1;  
  9.     bool esc false 
  10.     bool quote false 
  11.     int k;  
  12.     bool haveCmdNum !mWithSeq;  
  13.   
  14.     memset(argv, 0, sizeof(argv));  
  15.     memset(tmp, 0, sizeof(tmp));  
  16.     while(*p)  
  17.         if (*p == '\\')                //if (*p == '\')  
  18.             if (esc)            
  19.                 if (q >= qlimit)   
  20.                     goto overflow;    
  21.                 *q++ '\\'             
  22.         SLOGE("Faking timeout");  
  23.         goto out;  
  24.      
  25.     //只要是注册进来的命令都会进行调用rumcommand()  
  26.     for (i mCommands->begin(); != mCommands->end(); ++i)  
  27.         FrameworkCommand *c *i;  
  28.         if (!strcmp(argv[0], c->getCommand()))  
  29. ////////////////////////////////////////////////////////////////////////////  
  30.             if (c->runCommand(cli, argc, argv)) {//    runcommand()  ////  
  31. ////////////////////////////////////////////////////////////////////////////  
  32.                 SLOGW("Handler '%s' error (%s)"c->getCommand(), strerror(errno));  
  33.              
  34.             goto out;  
  35.          
  36.      
  37.   
  38.     cli->sendMsg(500, "Command not recognized"false);  
  39. out:  
  40.     int j;  
  41.     for (j 0; argc; j++)  
  42.         free(argv[j]);  
  43.     return 
  44.   
  45. overflow:  
  46.     LOG_EVENT_INT(78001, cli->getUid());  
  47.     cli->sendMsg(500, "Command too long"false);  
  48.     goto out;//错误处理  
  49.  

       经过解析匹配选择处理后调用runCommand 函数进行处理,该函数为定义在FrameworkCommand 中的纯虚函数,为子类提供接口,具体的实现在Commandlistnener 的各个XXXCmd 内部类中,例如下面的一个实例。

[cpp] viewplaincopy
  1. //CommandListener::XXXCmd.runCommand()  
  2. int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,  
  3.                                                       int argc, char **argv)  
  4.     int rc 0;  
  5.   
  6.     if (argc 2)  
  7.         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument"false);  
  8.         return 0;  
  9.      
  10.   
  11.     if (!strcmp(argv[1], "status"))  
  12.         char *tmp NULL;  
  13.   
  14.         asprintf(&tmp, "Forwarding %s"(sTetherCtrl->getIpFwdEnabled() "enabled" "disabled"));  
  15.         cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);  
  16.         free(tmp);  
  17.         return 0;  
  18.     else if (!strcmp(argv[1], "enable"))  
  19.         rc sTetherCtrl->setIpFwdEnabled(true);  
  20.     else if (!strcmp(argv[1], "disable"))  
  21.         rc sTetherCtrl->setIpFwdEnabled(false);  
  22.     else  
  23.         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd"false);  
  24.         return 0;  
  25.      
  26.   
  27.     if (!rc)  
  28.         cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded"false);  
  29.     else  
  30.         cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed"true);  
  31.      
  32.   
  33.     return 0;  
  34.  

     从上面代码的例子中可以看到调用了实际处理函数,一般为系统调用,他们将作用于系统,并将处理结果返回给 Framework层,并且至此我们又回到了 Netd/ 下。具体的命令的执行、实现。如何作用于系统都在 Netd 本地文件中的XXXController {.cpp | .h}中实现,涉及到 iptables,网络适配文件的读写等等。

     至此关于 Netlinkmanager + CommandListener整体的工作原理和工作流程就介绍完了,关于DnsProxyLis-tener 和 MDnsSdListener两部分大体的构架相同也同样使用到了 socket与上下两层进行通信,关于它们的的详细工作流程另做报告。关于以上部分使用到的主要的几大类,绘制了如下的粗略的类图:

 


 
 

0 0
原创粉丝点击