Android12的netd分析

1.文件位置

system/netd/server/目录下的main.cpp和Android.bp 可知编译会生成netd的可执行程序。

2.main函数的流程

cpp 复制代码
int main() {
    Stopwatch s;
。。。。。。。
// 启动NetlinkManager服务
    NetlinkManager *nm = NetlinkManager::Instance();
    if (nm == nullptr) {
        ALOGE("Unable to create NetlinkManager");
        exit(1);
    };
    gLog.info("NetlinkManager instanced");

    gCtls = new android::net::Controllers();
    gCtls->init();

    if (nm->start()) {
        ALOGE("Unable to start NetlinkManager (%s)", strerror(errno));
        exit(1);
    }

    std::unique_ptr<NFLogListener> logListener;
    {
        auto result = makeNFLogListener();
        if (!isOk(result)) {
            ALOGE("Unable to create NFLogListener: %s", toString(result).c_str());
            exit(1);
        }
        logListener = std::move(result.value());
        auto status = gCtls->wakeupCtrl.init(logListener.get());
        if (!isOk(result)) {
            gLog.error("Unable to init WakeupController: %s", toString(result).c_str());
            // We can still continue without wakeup packet logging.
        }
    }

    // Set local DNS mode, to prevent bionic from proxying
    // back to this service, recursively.
    // TODO: Check if we could remove it since resolver cache no loger
    // checks this environment variable after aosp/838050.
    setenv("ANDROID_DNS_MODE", "local", 1);
    // Note that only call initDnsResolver after gCtls initializing.
    if (!initDnsResolver()) {
        ALOGE("Unable to init resolver");
        exit(1);
    }

    MDnsSdListener mdnsl;
    if (mdnsl.startListener()) {
        ALOGE("Unable to start MDnsSdListener (%s)", strerror(errno));
        exit(1);
    }

    FwmarkServer fwmarkServer(&gCtls->netCtrl, &gCtls->eventReporter, &gCtls->trafficCtrl);
    if (fwmarkServer.startListener()) {
        ALOGE("Unable to start FwmarkServer (%s)", strerror(errno));
        exit(1);
    }

    Stopwatch subTime;
    status_t ret;
    if ((ret = NetdNativeService::start()) != android::OK) {
        ALOGE("Unable to start NetdNativeService: %d", ret);
        exit(1);
    }
    gLog.info("Registering NetdNativeService: %" PRId64 "us", subTime.getTimeAndResetUs());

    android::net::process::ScopedPidFile pidFile(PID_FILE_PATH);

    // Now that netd is ready to process commands, advertise service availability for HAL clients.
    sp<NetdHwService> mHwSvc(new NetdHwService());
    if ((ret = mHwSvc->start()) != android::OK) {
        ALOGE("Unable to start NetdHwService: %d", ret);
        exit(1);
    }
    gLog.info("Registering NetdHwService: %" PRId64 "us", subTime.getTimeAndResetUs());
    gLog.info("Netd started in %" PRId64 "us", s.timeTakenUs());

    IPCThreadState::self()->joinThreadPool();

    gLog.info("netd exiting");

    exit(0);
}

main.cpp主要启动了几个模块:

2.1 NetlinkManager

  • NetlinkManager:start()

setupSocket函数:

setupSocket创建了4个socket + handler用于接收来自SystemServer的网络相关的socket消息

NetlinkHandler的start函数

cpp 复制代码
    NetlinkHandler *handler = new NetlinkHandler(this, *sock, format);
    if (handler->start()) {  // 将创建的socket--启动线程接收
        ALOGE("Unable to start NetlinkHandler: %s", strerror(errno));
        close(*sock);
        return nullptr;
    }
cpp 复制代码
int NetlinkHandler::start() {
    return this->startListener();  // 调用---SocketListener::startListener
}

因为有这样的继承关系:

NetlinkHandler <------ NetLinkListener <--------- SocketListener

NetlinkHandler的start函数最后会调用到SockertListener:startListener

SockertListener:startListener

cpp 复制代码
int SocketListener::startListener(int backlog) { 
。。。。。。。。。。。。
    if (pthread_create(&mThread, nullptr, SocketListener::threadStart, this)) {
        SLOGE("pthread_create (%s)", strerror(errno));
        return -1;
    }

    return 0;
}

这里会去调用threadStart来监听socket消息, 最终会调用到SocketListener::runListener()

这个线程当收到消息则会进入NetlinkListener::onDataAvailable处理收到的消息

NetlinkListener::onDataAvailable

cpp 复制代码
bool NetlinkListener::onDataAvailable(SocketClient *cli)
{
    int socket = cli->getSocket();
。。。。。。。。

    NetlinkEvent *evt = new NetlinkEvent();
    if (evt->decode(mBuffer, count, mFormat)) {
        onEvent(evt);  // 根据不同的socket处理收到的消息
    } else if (mFormat != NETLINK_FORMAT_BINARY) {
        // Don't complain if parseBinaryNetlinkMessage returns false. That can
        // just mean that the buffer contained no messages we're interested in.
        SLOGE("Error decoding NetlinkEvent");
    }

    delete evt;
    return true;
}

最终进入NetlinkHandler::onEvent来处理socket事件。

2.2 DNS解析服务

监听来自framework的socket消息并处理

initDnsResolver() // 初始化dns服务类

cpp 复制代码
bool initDnsResolver() {
。。。。。。。。
    return resolv_init(&callbacks);   //  调用DnsResolver.cpp的方法
}

DnsResolver.cpp的resolv_init(&callbacks);

cpp 复制代码
bool resolv_init(const ResolverNetdCallbacks* callbacks) {  //
。。。。。。。。。。。。。。。
    android::net::gDnsResolv = android::net::DnsResolver::getInstance();  // 
    return android::net::gDnsResolv->start();  
// 即 DnsResolver::start方法
}

DnsResolver:start方法

cpp 复制代码
bool DnsResolver::start() {  //
。。。。。。。。
    if (mDnsProxyListener.startListener()) {  // 
        PLOG(ERROR) << __func__ << ": Unable to start DnsProxyListener";
        return false;
    }
。。。。。。。。。。
    return true;
}

存在此继承关系,SocketListener <------ FrameworkListener <----- DnsProxyListener

DnsProxyListener:startListener // 最终是调用到SocketListener::startListener

SockertListener:startListener

cpp 复制代码
int SocketListener::startListener(int backlog) { 
。。。。。。。。。。。。
    if (pthread_create(&mThread, nullptr, SocketListener::threadStart, this)) {
        SLOGE("pthread_create (%s)", strerror(errno));
        return -1;
    }

    return 0;
}

这里会去调用threadStart来监听socket消息, 最终会调用到SocketListener::runListener()

这个线程当收到消息则会进入FrameworkListener::onDataAvailable处理收到的消息

FrameworkListener::onDataAvailable

onDataAvailable会调用到FrameworkListener::dispatchCommand

cpp 复制代码
void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
    int argc = 0;
    char *argv[FrameworkListener::CMD_ARGS_MAX];
    char tmp[CMD_BUF_SIZE];
    char *p = data;
    char *q = tmp;
    char *qlimit = tmp + sizeof(tmp) - 1;
    bool esc = false;
    bool quote = false;
    bool haveCmdNum = !mWithSeq;
.......................

    for (auto* c : mCommands) {
        if (!strcmp(argv[0], c->getCommand())) {
            if (c->runCommand(cli, argc, argv)) {   // 执行command
                SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
            }
            goto out;
        }
    }
..........
}

getCommand是获取之前 DnsProxyListener的构造函数传入的接个cmd类。

runCommand来处理消息

DnsResolver.h的 class DnsResolver初始化变量

cpp 复制代码
class DnsResolver {
........
    DnsProxyListener mDnsProxyListener;   // 执行 DnsProxyListener 的构造函数
................
};

DnsResolver::start()

DnsProxyListener的构造函数----执行registerCmd函数----后续在收到消息后,会调用getCmd来拿到这里注册的Cmd

cpp 复制代码
DnsProxyListener::DnsProxyListener() : FrameworkListener(SOCKET_NAME) {  // 
    registerCmd(new GetAddrInfoCmd());
    registerCmd(new GetHostByAddrCmd());
    registerCmd(new GetHostByNameCmd());
    registerCmd(new ResNSendCommand());
    registerCmd(new GetDnsNetIdCommand());
}

runCommand会拿到找到registerCmd传入的Cmd来执行操作

相关推荐
海水冷却9 小时前
Android 群组聊天怎么实现:基于 ZIM 的完整落地指南(附可运行 Demo)
android
三少爷的鞋11 小时前
现代 Android 架构指南:不要再主动设计 Callback 接口
android
TimeFine17 小时前
AI 编码工作流的设计
android·ai编程
骑着蜗牛撵大象32717 小时前
C++20 协程 × 屏障:手写一个 co_await 版 Barrier,让等待不再钉死线程
android·c++20·协程·并发编程·co_await·屏障同步
山东孙燕姿19 小时前
设备台账重构:从一张表到三层模型
android·java·网络·低代码·重构·rxjava
蒸鱼Yuzheng20 小时前
移动端 CPU 调度分析:线程亲和性、大小核迁移与卡顿
android·perfetto·性能分析·线程优化·cpu调度
booboosui20 小时前
安卓唤醒词:12 维 MFCC 加 DTW,阈值 1.8
android
传奇开心果20 小时前
Compose Multiplatform 共享边界实战:架构契约、互操作同步与可回退设计
android·kotlin
事圆则缓21 小时前
从开机到首帧:Android 系统与应用启动流程源码分析
android
AI吃大瓜21 小时前
指针压力表读数4:Android实现指针压力表读数(可实时检测)
android·指针读数·指针压力表·压力表·压力表读数