Android Netd处理流程分析

摘要:本文对Android Netd处理流程做整体上的分析。

1. 介绍

Netd是Android系统中专门负责网络管理和控制的后台daemon程序, 其功能主要分三部分。

  • 设置防火墙(Firewall)、网络地址转换(NAT)、带宽控制、无线网卡软接入点(Soft Access Point)控制,网络设备绑定(Tether)等。
  • Android系统中DNS信息的缓存和管理。
  • 网络服务搜索(Net Service Discovery,NSD)功能, 包括服务注册(Service Registration)、服务搜索(Service Browse)和服务名解析(Service Resolve)等。

Netd的工作流程可分成两部分:

  • Netd接收并处理来自Framework层中NetworkManagementService或NsdService的命令(也可能是其它进程发送的命令)。 这些命令最终由Netd中对应的Command对象去处理。
  • Netd接收并解析来自Kernel的UEvent消息, 然后再转发给Framework层中对应Service去处理。

接下来以流程这条线来分析Netd。

2. 流程分析

Netd位于Framework层和Kernel层之间,它是Android系统中网络相关消息和命令转发及处理的中枢模块。流程图如下,接下来以该图来说明:

Netd处理框架

2.1. 由下往上的过程

首先描述Netd是如何接将Kernel的UEvent消息通知给Android Framework层:

  • ①.当执行某些操作(例如WIFI开启操作)时,Driver会产生相应事件(添加wlan0事件)。
  • ②.此时Kenerl会通过Socket(mUeventSock)上报给对应的SocketListener(mUeventHandler)。
  • ③.SocketListener子类实现NetlinkHandler.onEvent()将被执行,最终调用NetlinkHandler.notify()->NetlinkManager.getBroadcaster().sendBroadcast()即CommandListener.sendBroadcast()。
  • ④.CommandListener继承自FrameworkListener,FrameworkworkListener继承自SocketListener,因此最终执行的是SocketListener.sendBroadcast()。这里不纠结SocketListener.sendBroadcast()如何实现,通过名字可知道它将驱动产生的事件通知给所有连接netd的客户端。
  • ⑤.NativeDaemonConnector作为侦听netd的客户端会收到事件消息,并解析后通过消息机制传给NetworkManagerService。

2.2. 由上往下的过程

接下来描述Android Framework层如何将请求消息发送给Netd:

  • ⑥.当Framework层请求操作(例如开启nat)时,NetworkManagerService会通过NativeDaemonConnector将消息经过netd socket传递给Netd中的SocketListener。
  • ⑦.netd侦听实现为CommandListener,继承关系为CommandListener->FrameworkListener->SocketListener,当收到消息时FrameworkListener.onDataAvailable()会被执行,接下来会执行FrameworkListener.dispatchCommand(),它将解析从Framework中发下来的数据,并通过解析出的命令匹配到到CommandListener中注册的FrameworkCommand,并执行FrameworkCommand.runCommand()。

2.3. 另一条通路

在前面描述中,讲解的是netd socket(/dev/socket/netd)如何进行进程间通信处理。接下来以dnsproxyd为例讲解另外一条处理流程。
以bionic的libc中gethostbyaddr为例(代码位于/bionic/libc/dns/net/gethnamaddr.c),该函数返回对应于给定地址的包含主机名字和地址信息:

  • ⑧.函数调用流程为:gethostbyaddr->android_gethostbyaddrfornet_proxy->android_gethostbyaddrfornet_proxy_internal。
    其中android_gethostbyaddrfornet_proxy_internal将执行android_open_proxy()打开并连接DNS代理socket(/dev/socket/dnsproxyd),如何有代理,那么将向dnsproxyd发送命令gethostbyaddr
  • ⑨DNSProxyListener继承自FrameworkListener用来接收来自dnsproxyd的消息。同CommandListener一样,它注册了几个FrameworkCommand子类,命令”gethostbyaddr”被解析后对应了子类GetHostByAddrCmd,并执行GetHostByAddrCmd.runCommand。

3. 总结

上一节大致描述了Netd的处理流程,对具体有哪些命令以及mdns、fwmarkd此类socket并未详细描述。不做描述的原因是牵扯东西太多,例如iptables、 tc和ip等,不花点精力很难搞透彻。这里只做个整体上的描述,具体细节可以参考《深入理解Android:WiFi模块 NFC和GPS卷》。