当前位置: 首页 > news >正文

Android 7系统网络(三)Native层(上)—netd守护进程与CommandListener

系列目录:第一篇:全景图与调用链路概览 | 第二篇:内核层—netfilter/iptables与路由策略 |第三篇:Native层(上)—netd守护进程与CommandListener| 第四篇:Native层(下)—netd Controller详解 | 第五篇:Framework层(上)—ConnectivityService核心机制 | 第六篇:Framework层(下)—NMS/NPMS/NSS三大服务 | 第七篇:连接建立—WiFi/移动数据/以太网完整流程 | 第八篇:应用API层—ConnectivityManager使用与实战调试


一、netd 是什么

netd 全称 Network Daemon,是 Android 网络管理的核心守护进程。它运行在 Native 层,向上接收 Framework 的命令,向下操作内核的网络配置。理解 netd 的架构是理解整个 Android 网络系统的关键。

netd 的核心职责:

┌─────────────────────────────────────────────┐ │ netd (Network Daemon) │ │ │ │ ┌──────────────────┐ ┌──────────────────┐ │ │ │ CommandListener │ │ NetlinkManager │ │ │ │ 接收Framework命令 │ │ 监听内核UEvent │ │ │ └────────┬─────────┘ └────────┬─────────┘ │ │ │ │ │ │ ┌────────▼─────────────────────▼─────────┐ │ │ │ Controller 层 │ │ │ │ NetworkController RouteController │ │ │ │ FirewallController BandwidthController │ │ │ │ TetherController SoftapController │ │ │ │ IdletimerController │ │ │ └────────┬──────────────────────────────┘ │ │ │ │ │ ┌────────▼──────────────────────────────┐ │ │ │ DnsProxyListener → DNS 代理 │ │ │ └───────────────────────────────────────┘ │ └─────────────────────────────────────────────┘ │ │ ┌────▼────┐ ┌─────▼──────┐ │ 内核层 │ │ Framework │ │iptables │ │ 层服务 │ │路由表 │ │ │ └─────────┘ └────────────┘

关键设计:netd 采用"南北向分离"架构——北向通过CommandListenerDnsProxyListener与 Framework/应用通信,南向通过NetlinkManager和 Controller 操作内核,中间由 Controller 层将命令翻译为具体的 iptables 规则和 netlink 消息。


二、netd 启动流程

2.1 init.rc 中的定义

源码路径system/netd/server/netd.rc

servicenetd /system/bin/netd class main socket netd stream 0660 root system socket dnsproxyd stream 0660 root inet socket mdns stream 0660 root system socket fwmarkd stream 0660 root inet

关键设计:所有 Socket 都是stream类型(TCP),而不是dgram(UDP)。netd 的命令协议基于文本行,需要可靠的面向连接传输。

四个 Socket:

Socket类型权限用途
netdstream (TCP)0660 root systemFramework 控制通道
dnsproxydstream (TCP)0660 root inetDNS 代理
mdnsstream (TCP)0660 root system多播 DNS (mDNS)
fwmarkdstream (TCP)0660 root inetfwmark 设置

2.2 main.cpp 入口

源码路径system/netd/server/main.cpp

intmain(){// 1. 日志初始化// 2. 创建并启动 NetlinkManager// 3. 创建并启动 CommandListener// 4. 创建并启动 DnsProxyListener// 5. 创建并启动 MDnsSdListener(用于 mDNS/DNS-SD 服务发现)// 6. 创建并启动 FwmarkServer// 7. 进入主循环(等待事件)}

关键设计main()遵循"先启动基础设施,再启动服务"的顺序——NetlinkManager 在内核事件监听就绪后,才启动 CommandListener 接收 Framework 命令,最后启动 DNS 代理和 FwmarkServer 等面向应用的 Socket 服务。

启动顺序很重要:

main() ├── NetlinkManager::start() // 1. 先启动内核事件监听 ├── CommandListener::startListener() // 2. 启动命令监听 ├── DnsProxyListener::startListener() // 3. DNS 代理 ├── MDnsSdListener::startListener() // 4. mDNS └── FwmarkServer::startListener() // 5. fwmark

关键设计:NetlinkManager 须先于其他组件启动,因为 NetworkController 和 RouteController 等依赖它接收的内核事件来维护接口状态。


三、CommandListener 架构

3.1 整体设计

源码路径system/netd/server/CommandListener.h

classCommandListener:publicFrameworkListener{// ...};

源码路径system/netd/server/CommandListener.cpp

CommandListener 继承自 FrameworkListener,而 FrameworkListener 又继承自 SocketListener。这种多层继承体现了 Android 系统服务的通用设计模式:

SocketListener ← 通用 Socket 监听(libsysutils) ↑ FrameworkListener ← Android Framework 专用监听(libsysutils) ↑ CommandListener ← netd 的具体命令分发

关键设计SocketListener提供 socket 的创建、监听和事件分发,FrameworkListener在其上增加命令解析和响应码机制,CommandListener只负责注册各 Controller 的具体命令——三层各司其职,任意一层可独立替换。

3.2 命令注册机制

CommandListener 在构造函数中为每个 Controller 注册命令:

CommandListener::CommandListener(){// 注册各 Controller 的命令registerCmd(newInterfaceCmd());// interface 命令族registerCmd(newIpFwdCmd());// ipfwd 命令族registerCmd(newTetherCmd());// tether 命令族registerCmd(newNatCmd());// nat 命令族registerCmd(newResolverCmd());// resolver 命令族registerCmd(newBandwidthControlCmd());// bandwidth 命令族registerCmd(newFirewallCmd());// firewall 命令族registerCmd(newIdletimerCmd());// idletimer 命令族registerCmd(newStrictCmd());// strict 命令族registerCmd(newNetworkCmd());// network 命令族// 等等...}

关键设计:每个 Cmd 类对应一个命令族,例如InterfaceCmd可以处理interface listinterface getcfginterface setcfg等子命令——命令族内的子命令通过runCommand()argc/argv参数进一步分发。

每个 Cmd 类对应一个命令族,例如InterfaceCmd可以处理interface listinterface getcfginterface setcfg等子命令。

3.3 命令执行流程

当 NetworkManagementService 通过 Socket 发送一条命令时,完整的执行流程:

NetworkManagementService (Java) │ │ NativeDaemonConnector.execute("interface list") │ (通过 /dev/socket/netd socket 发送) │ ▼ CommandListener::onDataAvailable() │ │ 读取一行:"interface list" │ ▼ FrameworkListener::dispatchCommand("interface list") │ │ 解析命令名 "interface",查找对应的 Cmd 对象 │ ▼ InterfaceCmd::runCommand(client, argc, argv) │ argv[0] = "interface", argv[1] = "list" │ ▼ NetworkController::getInterfaceList() │ │ 读取 /proc/net/dev 或调用 ioctl │ ▼ 返回字符串:"200 wlan0 rmnet_data0 lo" │ │ 通过 Socket 返回给 NetworkManagementService │ ▼ NetworkManagementService 收到 "200 wlan0 rmnet_data0 lo" │ │ NativeDaemonConnector 解析响应码 "200" │ ▼ 调用方得到结果

关键:整条命令链路从 Java 层到 Native 层再到内核,每个环节的职责清晰——NativeDaemonConnector负责协议封装,CommandListener负责命令分发,Controller 负责执行操作,响应码200表示全程成功。

3.4 通信协议

netd 与 Framework 之间的协议非常简单:字符串命令 + 数字响应码

请求格式:

<命令名> [参数...]

响应格式:

<响应码> [内容]

响应码约定:

响应码含义
200成功
400客户端错误(参数错误)
500服务端错误(命令执行失败)
600命令未找到
213表示后面还有多行数据(每行后跟 213 继续,直到 200 结束)

多行响应示例:

213 00 01 02 03 04 05 06 00 00 00 00 00 00 00 00 00 00 213 01 02 03 04 05 06 07 00 00 00 00 00 00 00 00 00 00 200 Interface list completed

四、NetlinkManager — 内核事件监听

4.1 netlink 协议简介

netlink 是 Linux 中内核与用户态通信的一种机制。Android 用它来接收内核网络事件:

内核 用户态 (netd) │ │ │ 接口 wlan0 UP │ │ ↓ │ │ 生成 RTM_NEWLINK 消息 │ │ ↓ │ │ 通过 netlink socket 发送 ────→ NetlinkManager.handleEvent() │ │ ↓ │ │ NetlinkHandler.onEvent() │ │ ↓ │ │ 更新接口状态

关键:netlink 是内核主动推送事件给用户态的唯一通道——不需要轮询,接口状态变化(UP/DOWN)、地址变更、路由变更都在毫秒级到达 netd,然后通过广播通知 Framework 层。

4.2 NetlinkManager 实现

源码路径system/netd/server/NetlinkManager.cpp

classNetlinkManager{NetlinkHandler*mHandler;intmSock;// netlink socket fdintstart();intstop();};

关键设计NetlinkManager是单例模式,内部通过setupSocket()创建多个 netlink socket 分别监听 UEvent、路由、配额和严格模式四种事件,每种事件由独立的NetlinkHandler处理。

源码路径system/netd/server/NetlinkHandler.cpp

classNetlinkHandler:publicNetlinkListener{virtualvoidonEvent(NetlinkEvent*evt);};

关键设计NetlinkHandler继承自NetlinkListener(负责 netlink socket 的数据读取),onEvent()是事件分发的核心入口——根据事件的subsystemaction字段路由到不同的notify*()方法,最终通过广播通知 Framework 层。

onEvent方法处理以下类型的事件:

事件类型含义处理方式
RTM_NEWLINK接口创建/状态变化更新接口列表
RTM_DELLINK接口删除清理接口数据
RTM_NEWADDR新 IP 地址更新地址信息
RTM_DELADDRIP 地址删除清理地址信息
RTM_NEWROUTE新路由更新路由表缓存
RTM_DELROUTE路由删除清理路由缓存

4.3 NetlinkEvent 结构

源码路径system/core/include/sysutils/NetlinkEvent.h

每个 netlink 事件被解析成 NetlinkEvent 对象:

classNetlinkEvent{intmAction;// ACTION_ADD / ACTION_REMOVE / ACTION_CHANGEstd::string mSubsystem;// "net"std::string mInterfaceName;// "wlan0"std::map<std::string,std::string>mParams;// 键值对参数};

关键设计NetlinkEvent将内核的二进制 netlink 消息解析为结构化的字段——mAction表示增删改,mSubsystem区分事件来源(net/qlog/strict),mParams以键值对存储具体参数(如 ADDRESS、PREFIX、FLAGS),方便上层按名取值而非按位解析。

例如,当 wlan0 获得 IP 地址 192.168.1.100 时:

Action: ADD Subsystem: net Interface: wlan0 Params: {"ADDRESS": "192.168.1.100", "PREFIX": "24", "FLAGS": "128"}

关键:这个结构化的 NetlinkEvent 会被NetlinkHandler::onEvent()解析,识别出kAddressUpdated动作,然后通过广播通知 Framework 层"wlan0 获得了新 IP 地址",触发后续的路由配置流程。


五、DnsProxyListener — DNS 代理

5.1 为何需要 DNS 代理

传统 Linux 上,每个进程直接读取/etc/resolv.conf并自行发起 DNS 查询。但在 Android 中:

  • 不同网络(WiFi / 移动数据 / VPN)有不同的 DNS 服务器
  • 需要按应用控制 DNS(如 VPN 应用使用 VPN 的 DNS)
  • 需要统一 DNS 缓存

因此,Android 将所有 DNS 请求拦截到 netd 的 dnsproxyd socket,由 netd 统一代理。

5.2 代理流程

APP 调用 getaddrinfo("www.google.com") │ │ libc 中的 DNS 解析代码 │ (bionic/libc/dns/) │ ▼ 连接 /dev/socket/dnsproxyd │ │ 发送 DNS 查询请求(二进制格式) │ ▼ DnsProxyListener::DnsProxyListener() │ │ 解析请求,转发给 ResolverController │ ▼ ResolverController::getDnsForwarders(netId) │ │ 根据 netId 获取对应的上游 DNS 服务器 │ ▼ 发送 DNS 查询到上游服务器 (8.8.8.8 等) │ │ 收到响应 │ ▼ 通过 dnsproxyd socket 返回给 APP

关键:DNS 代理的流程是"应用发请求 -> netd 转发 -> 上游 DNS 响应 -> netd 回传"——应用只跟/dev/socket/dnsproxyd通信,完全不知道真正的 DNS 服务器是谁,netd 根据 netId 透明地选择了正确的上游服务器。

源码路径system/netd/server/DnsProxyListener.cpp

5.3 按 netId 管理 DNS

每个网络有独立的 DNS 服务器配置:

ResolverController 中存储的数据结构: netId → [ "8.8.8.8", "8.8.4.4", "dns.example.com" ]

关键ResolverController内部维护一个netId -> DNS服务器列表的映射表,Framework 通过resolver setnetdns命令写入,DNS 查询时根据请求 socket 的 netId 查找对应的上游服务器,实现不同网络使用不同 DNS。

设置 DNS 服务器的命令:

resolver setnetdns <netId> <domain> <dns1> <dns2> ...

六、FwmarkServer — Socket 标记

6.1 FwmarkServer 的作用

源码路径system/netd/server/FwmarkServer.cpp

当应用需要将自己的 Socket 绑定到特定网络时,需要设置 fwmark:

// ConnectivityManager 中的方法network.bindSocket(socket);

该操作最终通过/dev/socket/fwmarkd发送命令到 netd 的 FwmarkServer:

APP │ │ network.bindSocket(socket) │ ▼ ConnectivityManager │ │ 通过 JNI 调用 native 方法 │ ▼ 通过 /dev/socket/fwmarkd 发送:<socket_fd> <netId> <explicit> │ ▼ FwmarkServer 收到命令 │ │ 调用 setsockopt(socket_fd, SOL_SOCKET, SO_MARK, fwmark) │ ▼ 内核为该 Socket 设置 fwmark │ │ 此后该 Socket 的数据包走对应 netId 的路由表 │ ▼ 所有从该 Socket 发出的数据包都走正确的网络出口

关键FwmarkServer是 fwmark 机制的用户态入口——应用调用network.bindSocket()后,通过setsockopt(SO_MARK)将 fwmark 写入 socket 的内核数据结构,此后该 socket 的所有数据包会自动被策略路由匹配到正确的路由表。


七、小结

本篇覆盖了 netd 的三大核心模块:

模块方向作用
CommandListener上(接 Framework)接收并分发网络管理命令
NetlinkManager下(接内核)监听内核网络事件并处理
DnsProxyListener上(接应用)代理所有进程的 DNS 请求

下一篇将逐一拆解 netd 内部的八个 Controller,它们才是真正执行网络操作的核心。

http://www.jsqmd.com/news/1167497/

相关文章:

  • 去中心化 AI 推理网络的节点信誉系统:质押、挑战与罚没机制的设计
  • Python+AI数据分析实战:从环境搭建到智能报告生成
  • 隔离驱动芯片,如何安全、高效地驱动高压功率器件?
  • order-book-dynamics代码实现原理:深入解析SVM和决策树算法应用
  • 戴森球计划工厂蓝图库:3000+专业设计助你快速建造太空工厂
  • 建立/保持时间
  • Java字节码查看器完整指南:轻松掌握逆向工程核心工具
  • 如何快速部署蓝奏云直链解析API:面向初学者的完整指南
  • MagpieTTS Multilingual 357M性能优化:提升推理速度与语音质量的终极技巧
  • 2026年AI文献阅读工具实测对比:沁言学术、ReadPaper、Scholarcy、知网研学
  • 3大核心功能解密:如何用mytv-android打造你的专属电视直播中心
  • Visual C++运行库终极解决方案:一站式解决Windows DLL缺失问题
  • 3步革命:用Playnite构建你的终极游戏库统一中心
  • 北大教授流传版炒股PPT全文核心提炼+客观点评
  • 如何永久保存微信聊天记录?WeChatMsg开源工具让你轻松备份珍贵记忆
  • GBFR-Logs:数据驱动的《碧蓝幻想:Relink》战斗优化指南
  • 破解多平台直播数据采集的技术壁垒:WebSocket直连架构深度解析
  • A3910与STM32L4A6RG在电机控制中的低功耗设计实践
  • Kimi K2.5一句话开发实战:浏览器内生成可导出的轻量应用
  • 宝可梦存档管理器:从备份到编辑的完整解决方案
  • 2026 太仓正规黄金回收全面实测|无套路高价变现完整攻略 - 信息热点
  • Python股票数据获取终极指南:mootdx让通达信数据读取变得简单
  • iOS应用安装神器App Installer:5分钟掌握自由安装IPA文件的终极指南
  • 王爽《汇编语言》课程设计1:dtoc子程序实现32位数字转字符串的3个关键点
  • GPT-5.6发布与Codex合并:AI行业变革的深度解析与未来展望
  • OpenRGB终极指南:免费开源RGB灯光统一控制软件
  • GrapesJS完整指南:5步从零构建可视化网页编辑器
  • 终极指南:3步免费实现VR视频转2D,免设备自由播放
  • C++17事件总线实现:类型安全、线程安全的发布订阅模式
  • 你的老Mac还能再战5年吗?OpenCore Legacy Patcher让旧设备焕发新生