前言:
Netd是Android系统中专门负责网络管理的守护进程。NetD是网络管家,封装了复杂的底层各种类型的网络
(NAT,PLAN,PPP,SOFTAP,TECHER,ETHO,MDNS等),隔离了底层网络接口的差异,给Framework
提供了统一调用接口,简化了网络的使用。主要工作分为2个部分:
1,接收并处理来自Framework层中NetworkManagementService或NsdService的命令。这些命令最终由Netd中
对应的Command对象去处理。
2,接收并解析来自Kernel的UEvent消息,然后再转发给Framework层中对应Service去处理。
Netd位于Framework层和Kernel层之间,它是android系统中网络相关消息和命令转发及处理的中枢。本文基于android 6.0
1,进程启动
Netd进程由init进程启动, 其在init.rc文件的配置如下:
service netd /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,具体作用如下,
netd socket: NetworkManagementService和netd进程进行进程间通信;
mdns socket: NsdService和netd进程进行进程间通信;
fwmarkd socket: kernel和netd进程进行通信;
当然,这四个socket之间是相互独立的。
主要代码路径如下,
system\netd
Netd进程的入口方法main.cpp的main方法,主要代码如下,
CommandListener *cl;
NetlinkManager *nm;
DnsProxyListener *dpl;
MDnsSdListener *mdnsl;
FwmarkServer* fwmarkServer;
•••
cl = new CommandListener();//创建CommandListener对象
nm->setBroadcaster((SocketListener *) cl);
if (nm->start()) { //启动NetlinkManager
•••
setenv("ANDROID_DNS_MODE", "local", 1); //Netd设置环境变量ANDROID_DNS_MODE为"local"
dpl = new DnsProxyListener(CommandListener::sNetCtrl); //创建DnsProxyListener对象
if (dpl->startListener()) {//开始监听dnsproxyd socket
•••
mdnsl = new MDnsSdListener();//创建MdnsSdListener对象
if (mdnsl->startListener()) {//开始监听mdns socket
•••
fwmarkServer = new FwmarkServer(CommandListener::sNetCtrl);
if (fwmarkServer->startListener()) {// 监听fwmarkd socket
•••
if (cl->startListener()) {// 监听netd socket
•••
主要是启动了4个子线程,监听4个socket。还启动了NetlinkManage, 负责接收并解析来自Kernel的UEvent消息。
2, Java层分析
Framework主要有关的类如下,
/frameworks/base/services/core/java/com/android/server/
NetworkManagementService.java
NativeDaemonConnector.java
这2个类都运行于系统服务所在的进程当中。
2.1 启动
SystemServer.java中启动NetworkManagementService有关代码如下,
networkManagement = NetworkManagementService.create(context);
ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
NetworkManagementService的create方法如下,
public static NetworkManagementService create(Context context) throws InterruptedException {
return create(context, NETD_SOCKET_NAME);
}
NETD_SOCKET_NAME是netd socket,定义如下,
private static final String NETD_SOCKET_NAME = "netd";
create方法主要代码如下,
final NetworkManagementService service = new NetworkManagementService(context, socket);
service.mThread.start();//启动线程
NetworkManagementService构造方法主要代码如下,
mConnector = new NativeDaemonConnector(
new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl, FgThread.get().getLooper());
mThread = new Thread(mConnector, NETD_TAG);//创建名为NetdConnector的子线程
首先构造NetdCallbackReceiver对象, NetdCallbackReceiver是一个内部类,主要用于处理来自 netd进程的消息。
然后利用NetdCallbackReceiver对象构造NativeDaemonConnector,
NativeDaemonConnector本质就是一个线程,定义如下,
final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdog.Monitor {
mThread其实就是指NativeDaemonConnector线程, service.mThread.start()这句话就是调用NativeDaemonConnector的run方法。
首先看NativeDaemonConnector构造方法,
NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl,
Looper looper) {
mCallbacks = callbacks; //跨进程回调
mSocket = socket;//netd socket
mResponseQueue = new ResponseQueue(responseQueueSize);//应答消息处理
mWakeLock = wl;
if (mWakeLock != null) {
mWakeLock.setReferenceCounted(true);
}
mLooper = looper;
mSequenceNumber = new AtomicInteger(0);
TAG = logTag != null ? logTag : "NativeDaemonConnector";
mLocalLog = new LocalLog(maxLogSize);
}
NativeDaemonConnector的run方法主要步骤如下,
1,打开socket,获取输入输出流,
socket = new LocalSocket();//创建socket对象
LocalSocketAddress address = determineSocketAddress();//获取socket地址,就是netd
socket.connect(address);//socket连接,和netd守护进程进行连接
InputStream inputStream = socket.getInputStream();//获取输入流
synchronized (mDaemonLock) {
mOutputStream = socket.getOutputStream();//获取输出流
}
mCallbacks.onDaemonConnected();//回调NetdCallbackReceiver的onDaemonConnected方法
2,开启for循环读取netd守护进程发送上来的消息,当然消息也分为2类,
A,一类是NativeDaemonConnector发送请求, netd守护进程处理完之后的回答消息。这一类的消息直接放入mResponseQueue中。
B, netd守护进程直接上报的消息,这一类消息回调NetdCallbackReceiver的onEvent方法进行处理。
2.2 发送socket
NetworkManagementService一些方法需要netd守护进程处理,例如
createVirtualNetwork方法,
mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0", secure ? "1" : "0");
removeNetwork方法
mConnector.execute("network", "destroy", netId);
addInterfaceToNetwork方法
modifyInterfaceInNetwork("add", "" + netId, iface);
removeInterfaceFromNetwork方法
modifyInterfaceInNetwork("remove", "" + netId, iface);
modifyInterfaceInNetwork方法如下,
mConnector.execute("network", "interface", action, netId, iface);
NativeDaemonEvent的execute发送包含命令的socket如下,
mOutputStream.write(rawCmd.getBytes(StandardCharsets.UTF_8));
这样,包含create/ destroy/ add/ remove等命令的字节就通过socket发送到netd进程了。