当前位置: 首页 > 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来执行操作

 

相关文章:

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("Una…...

OpenCV图像文件读写(6)将图像数据写入文件的函数imwrite()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将图像保存到指定的文件中。 函数 imwrite 将图像保存到指定的文件中。图像格式是根据文件名扩展名选择的&#xff08;参见 cv::imread 获取扩展…...

JVM(HotSpot):方法区(Method Area)

文章目录 一、内存结构图二、方法区定义三、内存溢出问题四、常量池与运行时常量池 一、内存结构图 1.6 方法区详细结构图 1.8方法区详细结构图 1.8后&#xff0c;方法区是JVM内存的一个逻辑结构&#xff0c;真实内存用的本地物理内存。 且字符串常量池从常量池中移入堆中。 …...

JWT的基础与使用

JWT&#xff08;JSON Web Token&#xff09; 是一种用于在各方之间传输信息的紧凑、安全的方式&#xff0c;常用于身份验证和授权。它以令牌的形式将用户信息编码后传输&#xff0c;可以确保数据的完整性和安全性。 1.JWT的结构 JWT 是一个基于 JSON 的令牌&#xff0c;由三部…...

处理 VA02修改行项目计划行(SCHEDULE LINES )报错:不可能确定一个消耗帐户

用户修改销售订单行项目 计划行(SCHEDULE LINES) &#xff0c;从 “CN”改为“CB”时候发生报错提示&#xff1a;不可能确定一个消耗帐户。 Not possible to determine a consumption account Message No. 06138 Diagnosis The system was not able to determine a consumpti…...

【AI基础】pytorch lightning 基础学习

传统pytorch工作流是首先定义模型框架&#xff0c;然后写训练和验证&#xff0c;测试循环代码。训练&#xff0c;验证&#xff0c;测试代码写起来比较繁琐。这里介绍使用pytorch lightning 部署模型&#xff0c;加速模型训练和验证&#xff0c;记录。 准备工作 1 安装pytorch…...

高通量测序技术--组蛋白甲基化修饰、DNA亲和纯化测序,教授(优青)团队指导:从实验设计、结果分析到SCI论文辅助

组蛋白甲基化修饰工具(H3K4me3 ChIP-seq)组蛋白甲基化类型也有很多种&#xff0c;包括赖氨酸甲基化位点H3K4、H3K9、H3K27、H3K36、H3K79和H4K20等。组蛋白H3第4位赖氨酸的甲基化修饰(H3K4)在进化上高度保守&#xff0c;是被研究最多的组蛋白修饰之一。 DNA亲和纯化测序 DNA亲…...

[极客大挑战 2019]RCE ME1

<?php error_reporting(0); if(isset($_GET[code])){$code$_GET[code];if(strlen($code)>40){die("This is too Long.");}if(preg_match("/[A-Za-z0-9]/",$code)){die("NO.");}eval($code); } else{highlight_file(__FILE__); }// ?>…...

计算机毕业设计 中医院问诊系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…...

FME辅助规划选址

1.需求&#xff1a;新建运动场馆 用地需求&#xff1a;至少1km*2km 找到符合要求的储备地块 2.已有资源&#xff1a;储备用地 现在城市地块储备比较充足&#xff0c;但都是不规则地块 找出可以建大型场馆的地块 3.问题分析 图斑内部可以放下1000*2000的矩形 4.解决思路…...

Unity中的GUIStyle错误:SerializedObject of SerializedProperty has been Disposed.

一运行就循环打印这个报错&#xff0c; 解决办法&#xff0c;每次改参数之后在HIerarchy中手动保存&#xff0c;就会停止循环打印&#xff0c;style中的字体也显示出来了&#xff0c; 或者 直接换个低版本的...

实战篇 | WSL迁移Linux系统到非系统盘(完整实操版)

1. 操作步骤 1.1 确认要导出的Linux系统是否存在&#xff08;可跳过&#xff09; # 终端命令 # 查看通过WSL安装的Linux系统列表 wsl -l1.2 导出Linux系统为tar包 # 终端命令 # 格式&#xff08;过&#xff09; wsl --export <Distribution Name> <File Name> #…...

增量式编码器实现原理

目录 概述 1 认识增量式编码器 1.1 概述 1.2 增量式编码器的特性 1.3 编码器的硬件 2 增量式编码器实现原理 2.1 编码器信号 2.2 正反转判断 概述 本文主要介绍增量式编码器实现原理&#xff0c;包括增量式编码器的特性&#xff0c;信号特性&#xff0c;以及如何使用编…...

数据集-目标检测系列-口罩检测数据集 mask>> DataBall

数据集-目标检测系列-口罩检测数据集 mask>> DataBall 数据集-目标检测系列-口罩检测数据集 mask 数据量&#xff1a;1W DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;享有百种数据集&#xff0c;持续增加中。 数据项目地址&#xff1a; gitcode: https…...

工作安排 - 华为OD统一考试(E卷)

2024华为OD机试(C卷+D卷)最新题库【超值优惠】Java/Python/C++合集 题目描述 小明每周上班都会拿到自己的工作清单,工作清单内包含n项工作,每项工作都有对应的耗时时长(单位h)和报酬,工作的总报酬为所有已完成工作的报酬之和。那么请你帮小明安排一下工作,保证小明在指定…...

STM32 GPIO - 笔记

1 STM32的GPIO是漏还是源 在 STM32 微控制器中,GPIO(通用输入/输出)引脚既可以配置为漏极开路输出(Open-Drain)模式,也可以配置为推挽输出(Push-Pull)模式。因此,GPIO 引脚既可以作为“漏”(吸电流,Open-Drain),也可以作为“源”(供电流,Push-Pull)来使用。 GP…...

三篇文章速通JavaSE到SpringBoot框架 (中) IO 进程线程 网络编程 XML MySQL JDBC相关概念与演示代码

文章目录 IOfile类的作用I/O的作用将上篇文章综合项目使用IO流升级所需知识点 进程 线程创建线程的三种方式 网络编程网络编程介绍IP地址端口号网络通信协议网络通信协议的分层演示代码 XMLXML的作用是什么&#xff1f;xml特点 注解什么是注解&#xff1f;注解的使用注解的重要…...

Linux下的基本指令/命令(二)

热键 Tab&#xff1a; 连点两次 对命令进补齐 或者 显式 以目前所需字母 开头的指令。 也可以进行路径补齐 或者 显示所写的文件所处路径上的所有文件。 如果什么也没写&#xff0c;直接按Tab会显示所有命令 Ctrl C&#xff1a; 一旦出现失控的状态&#xff0c;或者任何无法…...

CentOs-Stream-9 设置静态IP外网访问

CentOs-Stream-9 设置静态IP&#xff0c;实现外网访问。这里面有些需要注意的地方&#xff0c;比如IP网段跟我们的宿主机不一样&#xff0c;需要查看具体的网络适配器网段&#xff0c;这样可以快速实现网络互通&#xff1b;另外它的网络配置文件也是不一样的。网络适配器对应的…...

精密制造的革新:光谱共焦传感器与工业视觉相机的融合

在现代精密制造领域&#xff0c;对微小尺寸、高精度产品的检测需求日益迫切。光谱共焦传感器凭借其非接触、高精度测量特性脱颖而出&#xff0c;而工业视觉相机则以其高分辨率、实时成像能力著称。两者的融合&#xff0c;不仅解决了传统检测方式在微米级别测量上的局限&#xf…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...