NETD是Android一个专门管理网络链接, 路由/带宽/防火墙策略以及iptables的系统Daemon进程, 其在Anroid系统启动时加载 :
1 |
|
启动netd时, 会创建四个socket,用于其他进程与netd进行通信:
netd
: 主要与Framework的NetworkManagementService
交互, 用于控制网口状态, 路由表dnsproxyd
: DNS代理的控制与配置,用于私有DNS(DNS Over TLS)的请求转发mdns
: 多播DNS(Multicast DNS,参考RFChttps://tools.ietf.org/html/rfc6762), 用于基于WIFI连接的服务发现(NSD, Network Service Discovery)fwmarkd
: iptables的(fwmark)策略路由的配置(策略路由, 如设置网络权限, 连接打标签等
总的说来, netd进程在Android中间层服务NetworkManagementService
以及内核之间建立了一个沟通的桥梁:
- 对Java层系统服务
NetworkManagementService
,netd
通过socket接口为其提供了控制指令的通道 - 对内核,
netd
通过netlink socket与内核进行数据/指令的收发, 并将来自内核的消息发送给上层 - 从Android 8.0开始, Netd同时提供了一个HAL Binder的接口提供给其他进程调用
INetd.aidl
接下来, 本文从三个方面来看下netd
的具体工作原理与实现.
netd
的初始化与启动NetworkManagementService
与netd
的交互netd
与内核的交互
关于netlink socket可以参考: http://qos.ittc.ku.edu/netlink/html/node4.html
netd的启动与初始化
netd进程启动时, 主要处理做以下事情:
- 创建一个
NetlinkManager
, 用于管理与内核通信的netlink连接 - 初始化网络控制类, 如路由控制
RouteController
, 带宽控制BandwidthController
- 启动各类事件监听类:
DnsProxyListener
监听DNS代理;CommandListener
监听来自NetworkManagement
的指令 - 启动NetdHwService, 为HAL层提供接口
1 |
|
CommandListener
用于接收处理来自上层NetworkManagementService
指令, 在netd
启动时, 会监听netd
这个socket, 并允许最多4个客户端请求的处理:
1 |
|
这里创建了一个专门的线程用于处理来自上层客户端的命令请求:
- 检查控制pipe的数据,是否有必要停止监听;
- 监听来自客户端的请求, 如果有, 则新建一个
SocketClient
保存下来 - 从已有的
SocketClient
中检查是否有可用的数据, 如果有则通过onDataAvailable
1 |
|
netd启动完成后, 就可以处理来自中间层的指令请求以及与内核进行交互了.
netd与NetworkManagerService的交互
SystemServer
进程启动时, 创建NetworkManagementService
(以下简称(NMS
)), 此时NMS
会主动与netd
建立socket链接:
1 |
|
创建NMS时, 启动一个新的线程用于与netd通信,
1 |
|
NMS通过NativeDaemonConnector
与netd
建立socket通信, NativeDaemonConnector
主要做两个事情:
- 与
netd
建立一个数据链接 - 不断读取socket中的数据流: 一种是
netd
主动上报的命令, 一种是NMS发送给netd
后的指令的响应
1 |
|
socket链接建立完成之后, NMS与netd
可以相互通信, 发送指令与数据了. NMS通过NativeDaemonConnector
执行相应的指令, 比如NMS设置网络接口的配置(打开/关闭网口):
1 |
|
NativeDaemonConnector
会将每个指令都指定一个唯一的序列, 并将其响应放到一个阻塞队列, 等待netd
返回指令的结果, 如果超过指定的超时时间, 则抛出一个超时的异常.
在第一部分时, 讲到SocketListener
拿到上层发过来的指令后, 会将其分发给对应的指令类进行处理(看SocketListener
的子类FrameworkListener
):
1 |
|
函数dispatchCommmand
会检查所有指令处理类, 匹配相应的类去执行指令:
1 |
|
比如这里执行的是, 网络接口相关的设置, 因此会调用InterfaceCmd
来执行该指令.
NETD与内核进行交互
NETD通过netlink
事件与内核进行消息的交换.在第一部分时看到, netd
启动时, 会配置socket与内核进行通信:
- netlink事件
NETLINK_KOBJECT_UEVENT
: 用于内核向netd
发生消息, 如网口的状态变化; - netlink事件
NETLINK_ROUTE
:用于接收路由信息, 如路由表的更新与删除; - netlink事件
NETLINK_NFLOG
:用于接收数据流量使用配额的消息, 如数据使用超限; - netlink事件
NETLINK_NETFILTER
用于接收包过滤(netfilter)的消息;
1 |
|
每一个netlink的socket都会新建一个NetlinkHandler
, 用于处理内核的消息, 并将该消息广播给上层:
1 |
|
至此, Netd的介绍就结束了。 总的说来, Netd服务是Android网络管理的核心进程之一, 对于了解Android网络管理很有帮助, 看下其实现细节对于掌握网络相关的问题至关重要。