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

Android12的netd分析

1.文件位置

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

2.main函数的流程

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函数

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

因为有这样的继承关系:

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

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

SockertListener:startListener

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

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服务类

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

DnsResolver.cpp的resolv_init(&callbacks);

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

DnsResolver:start方法

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

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

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)) {   // 执行commandSLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));}goto out;}}
..........
}

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

runCommand来处理消息

DnsResolver.h的 class DnsResolver初始化变量 

class DnsResolver {
........DnsProxyListener mDnsProxyListener;   // 执行 DnsProxyListener 的构造函数
................
};

DnsResolver::start()

 

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

DnsProxyListener::DnsProxyListener() : FrameworkListener(SOCKET_NAME) {  // registerCmd(new GetAddrInfoCmd());registerCmd(new GetHostByAddrCmd());registerCmd(new GetHostByNameCmd());registerCmd(new ResNSendCommand());registerCmd(new GetDnsNetIdCommand());
}

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

 

http://www.lryc.cn/news/447191.html

相关文章:

  • OpenCV图像文件读写(6)将图像数据写入文件的函数imwrite()的使用
  • JVM(HotSpot):方法区(Method Area)
  • JWT的基础与使用
  • 处理 VA02修改行项目计划行(SCHEDULE LINES )报错:不可能确定一个消耗帐户
  • 【AI基础】pytorch lightning 基础学习
  • 高通量测序技术--组蛋白甲基化修饰、DNA亲和纯化测序,教授(优青)团队指导:从实验设计、结果分析到SCI论文辅助
  • [极客大挑战 2019]RCE ME1
  • 计算机毕业设计 中医院问诊系统的设计与实现 Java实战项目 附源码+文档+视频讲解
  • FME辅助规划选址
  • Unity中的GUIStyle错误:SerializedObject of SerializedProperty has been Disposed.
  • 实战篇 | WSL迁移Linux系统到非系统盘(完整实操版)
  • 增量式编码器实现原理
  • 数据集-目标检测系列-口罩检测数据集 mask>> DataBall
  • 工作安排 - 华为OD统一考试(E卷)
  • STM32 GPIO - 笔记
  • 三篇文章速通JavaSE到SpringBoot框架 (中) IO 进程线程 网络编程 XML MySQL JDBC相关概念与演示代码
  • Linux下的基本指令/命令(二)
  • CentOs-Stream-9 设置静态IP外网访问
  • 精密制造的革新:光谱共焦传感器与工业视觉相机的融合
  • 边缘计算与 Python Web 应用:从理论到实践
  • 华为OD机试真题------分糖果
  • Kotlin:变量声明,null安全,条件语句,函数,类与对象
  • C--结构体和位段的使用方法
  • 卷积神经网络-迁移学习
  • 数据库:PL/SQL
  • 迅雷笔试 最长相等子段数列长度 滑动窗口
  • MMD模型一键完美导入UE5-VRM4U插件方案(一)
  • bench.sh:一行命令测试Linux服务器基准测试
  • 广播IP与共享IP的关系
  • 正则表达式和re模块