企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
本节将介绍CL的构造函数以及Netd的测试工具ndc。 **1.CL构造函数** 在前文的2.2.3节中已经介绍了CL构造函数的前半部分,下面接着介绍CL构造函数的后半 部分,代码如下所示。 **CommandListener::CommandListener构造函数** ~~~ CommandListener::CommandListener() : FrameworkListener("netd", true) { ......// 创建命令和命令控制对象 // 初始化iptables中的各个Table及相应Chain和Rules // createChildChains第一个参数用于指明针对IPv4还是IPv6 createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT); createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD); createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT); createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING); createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING); createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING); createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING); // 4.2以后,Netd允许OEM厂商可自定义一些规则 // 这些规则在/system/bin/oem-iptables-init.sh文件中保存 setupOemIptablesHook(); // 初始化iptables中的一些chain,以及初始化路由表 sFirewallCtrl->setupIptablesHooks(); sNatCtrl->setupIptablesHooks(); sBandwidthCtrl->setupIptablesHooks(); sIdletimerCtrl->setupIptablesHooks(); // 初始时,Netd将禁止带宽控制功能 sBandwidthCtrl->enableBandwidthControl(false); ~~~ 由上述代码可知,CL构造函数的后半部分工作主要是利用iptables等工具创建较多的Chain和Rule,以及对某些命令控制对象进行初始化。 本节将重点关注iptables执行后的效果。图2-13所示为CL构造后,iptable中filter表内所创建的Chain和Rule。 图2-13中列出的是filter表中部分Chain的截图,其中,target是目标名,prot是protocol之意,opt是选项,source和destination分别表示数据包的源和目标地址。 - bw_INPUT、bw_OUTPUT和bw_FORWARD Chain用于带宽(Bandwidth)控制。 - fw_INPUT、fw_OUTPUT和fw_FORWARD用于防火墙(Firewall)控制。 - natctrl_FORWARD用于网络地址转换(NAT)控制。 - oem_fwd、oem_out用于OEM厂商自定义的控制。 :-: ![](https://box.kancloud.cn/235441efce178ae1fd37379644e22a57_534x557.jpg) 图2-13 CL创建后filter表的内容 **2.ndc测试工具** ndc是Android为Netd提供的一个测试工具。其主要功能有: - 监视Netd中发生的事情。 - 支持通过命令行发送命令给Netd去执行。 相信读者很轻松就能想到ndc的实现原理,其实它就是连接上位于netd进程中的"netd"监听socket,然后从Netd接收信息或发送命令给Netd。 图2-14为使用ndc monitor选项监控Galaxy Note 2打开Wi-Fi功能时得到的输出。 :-: ![](https://box.kancloud.cn/d02427829934de3c093e6e60b91f43f4_604x538.jpg) 图2-14 ndc monitor执行结果 利用ndc来监视Netd的工作状况是一个简单高效的方法。另外,还可利用ndc来测试CommandListener中所支持的各种命令。这对于网络相关模块的HAL层开发者来说无疑是一个很大的帮助。为了方便读者理解,本节下文也将利用ndc来展示命令执行的结果。 在正式介绍CL中的命令对象之前,先介绍这些命令对象处理的通用流程。 如图2-4所示,命令对象的真正控制函数是runCommand,而绝大部分命令的runCommand函数都有类似如下的代码结构(此处以InterfaceCmd为例)。 **CommandListener.cpp::InterfaceCmd:runCommand** ~~~ int CommandListener::InterfaceCmd::runCommand(SocketClient *cli, int argc, char **argv) { if (argc < 2) {// 先做参数检查 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false); return 0; } // 然后分别处理自己支持的各种命令选项 if (!strcmp(argv[1], "list")) { ......// 处理"list"选项 } else if (!strcmp(argv[1], "readrxcounter")) { ......// 处理"readrxcounter"选项 } ......// 处理其他选项 } ~~~ 由上述InteraceCmd的处理函数可知,runCommand的处理流程如下。 1)首先参数检查,一般是检查参数个数是否正确。 2)然后根据不同的选项进行对应的处理。 * * * * * **提示** 接下来分析CL中各个命令,由于其中涉及较多的知识,因此单独增加“背景知识介绍”小节以帮助读者更好地理解它们。 * * * * *