NetD初探

netd是Android与Linux网络模块之间的接口,类似于RILD和Modem的关系。JAVA层的通过socket与netd交互。

framework层定义了系统服务NetworkManagementService来提供netd相关处理的接口,再通过NativeDaemonConnector实现与Netd交互。

下面先分析下JAVA层入口:


1.NetworkManagementService
NetworkManagementService是AIDL接口的实现类,属于System进程并由watchdog守护。
public class NetworkManagementService extends INetworkManagementService.Stub implements Watchdog.Monitor

2.NetworkManagementService的启动
开机后由SystemServer初始化:
</pre><pre>

try {Slog.i(TAG, "NetworkManagement Service");
    networkManagement = NetworkManagementService.create(context);
    ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
} catch (Throwable e) { <span style="font-family: Arial, Helvetica, sans-serif;">reportWtf("starting NetworkManagement Service", e);}</span>

    

NetworkManagementService::create方法会创建实例,并执行一个子线程。

static NetworkManagementService create(Context context, String socket) throws InterruptedException {
        final NetworkManagementService service = new NetworkManagementService(context, socket);
        final CountDownLatch connectedSignal = service.mConnectedSignal;
        service.mThread.start();<span style="color:#ff0000;">//子线程中执行操作</span>
        connectedSignal.await();
        return service;
    }
</pre><pre name="code" class="java">    public static NetworkManagementService create(Context context) throws InterruptedException {
        return create(context, NETD_SOCKET_NAME);<span style="color:#ff0000;">//指定netd socket的名字</span>
    }

NetworkManagementService::create中所启动的线程就是用来执行NativeDaemonConnector::run()的,即用于对netd socket的监听,具体请看4. NativeDaemonConnector初始化


3. NativeDaemonConnector
NativeDaemonConnector类实现了Runnable,Handler.Callback和watchdog monitor
final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdog.Monitor 

其run方法循环监听netd上报的消息,listenToSocket收到消息后发送给mCallbackHandler处理:
    public void run() {
        mCallbackHandler = new Handler(mLooper, this);
        while (true) {
            try {
                listenToSocket();<span style="font-family: Arial, Helvetica, sans-serif;">//监听来自netd Socket的消息</span>
            } catch (Exception e) {
                loge("Error in NativeDaemonConnector: " + e);
                SystemClock.sleep(5000);
            }
        }
    }



4. NativeDaemonConnector初始化

NativeDaemonConnector在NetworkManagementService构造函数中初始化:

private NetworkManagementService(Context context, String socket) {

...
        <span style="color:#ff0000;">//NetdCallbackReceiver接收NativeDaemonConnector回发的消息</span>
        mConnector = new NativeDaemonConnector(new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl, FgThread.get().getLooper());
        mThread = new Thread(mConnector, NETD_TAG); <span style="color:#ff0000;">//新建线程</span>
...

}


新建的线程用于执行NativeDaemonConnector::run(),及调用listenToSocket()循环监听socket。


5. 监听来自netd消息:
监听消息处理在NativeDaemonConnector::listenToSocket中执行,接收到之后发送到Handler处理,并回调NetworkManagementService内部的NetdCallbackReceiver::onEvent()



6. 向netd发送执行命令:

NetworkManagementService提供了大量netd支持的接口, 都会通过NativeDaemonConnector发送至netd:



NativeDaemonConnector::execute接口用于接受具体命令,以NetworkManagementService::setDefaultNetId为例,传入命令参数是"network" + "default" + "set" + netId:

    public void setDefaultNetId(int netId) {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);

        try {
            mConnector.execute("network", "default", "set", netId);
        } catch (NativeDaemonConnectorException e) {
            throw e.rethrowAsParcelableException();
        }
    }

最后NativeDaemonConnector::executeForList 通过socket outstream向netd发送命令:

public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args)
            throws NativeDaemonConnectorException {

...
        makeCommand(rawBuilder, logBuilder, sequenceNumber, cmd, args);
        log("SND -> {" + logCmd + "}");

        synchronized (mDaemonLock) {
            if (mOutputStream == null) {
                throw new NativeDaemonConnectorException("missing output stream");
            } else {
                try {
                    mOutputStream.write(rawCmd.getBytes(StandardCharsets.UTF_8));
                } catch (IOException e) {
                    throw new NativeDaemonConnectorException("problem sending command", e);
                }
            }
        }
...

}



7. netd

netd作为linux服务,在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


netd代码在/system/netd目录下,按照每个功能定义了处理模块,如Tethering相关功能由TetherController.cpp处理:


CommandListener.cpp是处理命令的入口,分解命令后指定对应的模块函数来处理。

以setDefaultNetId为例:

int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {

...
if (!strcmp(argv[1], "<span style="background-color: rgb(255, 102, 102);">default</span>")) {
        if (argc < 3) {
            return syntaxError(client, "Missing argument");
        }
        unsigned netId = NETID_UNSET;
        if (!strcmp(argv[2], "set")) {
            if (argc < 4) {
                return syntaxError(client, "Missing netId");
            }
            netId = stringToNetId(argv[3]);
        } else if (strcmp(argv[2], "clear")) {
            return syntaxError(client, "Unknown argument");
        }
        if (int ret = sNetCtrl->setDefaultNetwork(netId)) {
            return operationError(client, "setDefaultNetwork() failed", ret);
        }
        return success(client);
    }
...

}


这个只是netd的入口,具体实现涉及到linux网络模块各方面,后面有时间再深入分析。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值