net学习总结

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

一、rc文件启动

二、main函数

三、netlinkmanager分析

四、NetdNativeService分析

五、NetdworkManagemenrService初始化

一、rc 文件启动

netd进程是一个可执行的bin文件程序,而通常它的启动方式一般都是init.xxx.rc进行启动的,但是在Android5以及之后Android已经将rc权利下放到各个子模块中,然后通过import导入了,netd的启动也不例外下放到了netd.rc中。

启动时创建4个监听socket

1)/dev/socket/networksliced将用于和NetworkSliceController进行双向通信,而NetworkSliceController主要用来发送消息给slicedatamonitor

2)/dev/socket/dnsproxyd将用于和Netd中的DnsproxyListener来进行双向通信,而DnsproxyListener主要用来完成Dns的相关操作;

3)/dev/socket/mdns将用于和Netd中的MdnsSdListener来进行双向通信,而MdnsSdListener主要用来完成mdnsd的操作;

4)/dev/socket/fwmarkd将用于和Netd中的FwmarkServer来进行双向通信,而FwmarkServer用于对特定的socket设置mark值。

二、main函数

1)创建一个NetlinkManager, 用于管理与内核通信的netlink连接

a) NetlinkManager:它将接收并处理来自Kernel的UEvent消息。这些消息经NetlinkManager解析后将借助它的Broadcaster(也就是代码中为NetlinkManager设置的CommandListener)发送给Framework层的NetworkManagementService

b) Netlinkmanager主要用于接收并处理来自kernel的UEvent消息,在NetlinkManager将会启动3个socket,用于监听3种不同的event:Uevent,RouteEvent,QuotaEvent。而对这种监听是通过SocketListener实现监听的,最终通过/dev/socket/netd送到NetworkManagementService(java代码),分配到注册到它里面的各个观察者实例(Ethernet,WIFI等)

2)初始化网络控制类, 如路由控制RouteController, 带宽控制BandwidthController

3)启动各类事件监听类: DnsProxyListener监听DNS代理;

4)创建 NetdNativeService、MDnsService服务注册到binder中,在framework层直接获取对应的引用对象

5)启动NetdHwService, 为HAL层提供接口

三、 netlinkmanager 分析

NetlinkManager:它将接收并处理来自Kernel的UEvent消息。这些消息经NetlinkManager解析后将借助它的Broadcaster(也就是代码中为NetlinkManager设置的CommandListener)发送给Framework层的NetworkManagementService。

main函数中分析创建NetlinkManager,用于管理与内核通信的netlink链接

第一个红框:创建NetlinkManager

第二个红框:初始化各控制类

第三个红框:启动NetlinkManager

start函数的通过setupSocket函数实现里创建了4个监听进程,分别监听NETLINK_KPROJECT_UEVENT消息、NETLINK_ROUTE消息、NETLINK_NFLOG消息和NETLINK_NETFILTER消息

  1. NETLINK_KOBJECT_UEVENT:代表kobject事件,由于这些事件包含的信息由ASCII字符串表达,故上述代码中使用了NETLINK_FOMRAT_ASCII。它表示将采用字符串解析的方法去解析接收到的UEvent消息。kobject一般用来通知内核中某个模块的加载或卸载。对NetlinkManager来说,其关注的是/sys/class/net下相应模块的加载或卸载消息,譬如以太网模块的加载和卸载。

  2. NETLINK_ROUTE:代表kernel中routing或link改变时对应的消息。NETLINK_ROUTE包含很多子项,上述代码中使用了RTMGRP_LINK项。二者结合起来使用,表示NM希望收到网络链路断开或接通时对应的UEvent消息(当网卡上拔掉或插入网线时,会触发这些UEvent消息的发送)。由于对应UEvent消息内部封装了nlmsghdr等相关结构体,故上述代码使用了NETLINK_FORMAT_BINARY来指示解析UEvent消息时将使用二进制的解析方法。

  3. NETLINK_NFLOG:和带宽控制有关。Netd中的带宽控制可以设置一个预警值,当网络数据超过一定字节数就会触发kernel发送一个警告,该代码也使用NETLINK_FORMAT_BINARY来指示解析UEvent消息时将使用二进制的解析方法。

  4. NETLINK_NETFILTER:和网络过滤有关系。

分析setupSocket流程,在该函数中创建socket,设置属性,buffer,credentials,bind()函数并start线程,开始监听,函数返回值为Netlinkhandler类型**(** 这个函数主要就是为 Android system_server/init 进程准备一个通道,用来接收来自内核的 netlink 消息 (NETLINK _ KPROJECT _ UEVENT 消息、 NETLINK _ ROUTE 消息、 NETLINK _ NFLOG 消息和 NETLINK_ NET FILTER 消息 ))

NetlinkHandler的作用:

1)用poll()/epoll监听netlink fd

2)不断recvmsg()

3)解析uevent或者RTNETLINK消息

4)最终把事件分发给Android上层

最重要的是调用start函数,该函数会启动netlink监听线程,整个Android接收uevent/RTNETLINK消息的能力都依赖它

调用startListener函数进入socket公共库中。该部分关注 pthread_create 函数,该函数会创建一个线程来专门监听 netlink 套接字,然后不停循环 recv() 内核消息,线程处理函数为 SocketListener::threadStart

线程处理函数中主要关注runListener()函数

runListener()才是真正的处理函数,使用了fd_set结构,使用了select函数,用于判断监听的kernel相关部分是否有event发出,如果有,则调用NetlinkListener中的onDataAvailable函数进行处理。

  1. 通过调用uevent_kernel_recv接收内核发送来的消息并将消息封装在mBuffer中,如果接收到数据则构建一个NetlinkEvent对象evt,调用其函数decode解析从kernel中接收到的数据。

2)onDataAvailable()中,通过NetlinkEvent中的decode方法将收到的event按照要求的格式进行解码,解码成功后调用onEvent方法进行处理。这里的onEvent函数也是纯虚函数。

分析uevent_kernel_recv函数,uevent_kernel_recv是用于从内核接收uevent(用户空间事件)消息的系统调用封装。通过Netlink套接字接收来自内核的消息,并验证消息消息来源和格式,确保安全性和正确性。调用recvmsg系统调用接收消息,使用TEMP_FAILURE_RETRY处理中断错误

decode解析kernel上报上来的消息,会解析两种消息

1)parseBinaryNetlinkMessage函数解析binary消息

2)parseAsciiNetlinkMessage函数解析ASCII消息

parseBinaryNetlinkMessage解析binary message,二进制消息包含RTM_NEWLINK,RTM_NEWADDR,RTM_DELADDR,RTM_NEWROUTE,RTM_DELROUTE,RTM_NEWNDUSEROPT等消息。其中for循环的作用:将buffer转换为Netlink消息头指针,并赋值给nh。

1)RTM_NEWLINK消息解析为kLinkUp或kLinkDown,mSubsystem赋值为net

2)LOCAL_QLOG_NL_EVENT消息解析为kChange,mSubsystem赋值为qlog

3)RTM_NEWADDR和RTM_DELADDR消息解析为kAddressUpdated或kAddressRemoved,mSubsystem赋值为net

4)RTM_NEWROUTE和RTM_DELROUTE消息解析为kRouteUpdated和kRouteRemoved,mSubsystem赋值为net

5)RTM_NEWNDUSEROPT消息解析为kRdnss,mSubsystem赋值为net

6)LOCAL_NFCAL_PACKET消息解析为kChange,mSubsystem赋值为strict

解析NETLINK_KOBJECT_UEVENT的ASCII形式的消息,

1)如果存在add,则解析为kAdd

2)如果存在remove,则解析为kRemove

3)如果存在change,则解析为kChange

解码成功后面将调用onEvent方法进行处理。至此,从netd/Netlinkmanager到公共库中的具体监听socket的实现,自上而下的监听就算完成了,该部分实现了kernel部分与netd的联系的建立。现在,处理流程又回到了netd部分,并且得到了解码成字符串形式的来自的event,接下来开始在netd部分进行处理,并将处理结果提交给framework层。onEvent函数对UEvent(已经转为NetlinkEvent)进行分类处理。

NETLINK_KOBJECT_UEVENT和NETLINK_ROUTE主要反映网络设备的事件和状态,包括NIC的添加,删除和修改,以及链路的连接状态等。NETLINK_NFLOG用于反映设置的log是否超过配置。另外,xt_idletimer的uevent消息,它和后文介绍的IdleTimerCmd有关,主要用来监听网络设备的收发工作状态。当对应设备工作或空闲时间超过设置的监控时间后,kernel将会发送携带其状态(idle或active)的UEvent消息**(如果需要给网卡配置信息,可以在这个里面通过system()进行配置)**。

这里以notifyInterfaceAdded为例:

这里通过宏函数,获取每个注册的NetdUnsolicitedListener,然后调用对应的函数,这里对应的函数为onInterfaceAdded,通过NetdUnsolicitedListener回调,netd成功将kernel上报的消息传到了framework层,至此完成了kernel事件经native层上报到framework层的工作。

LOG_EVENT_FUNC(BINDER_RETRY, onInterfaceAdded, ifName):当内核报告有新网络接口被创建时,NetlinkHandler调用notifyInterfaceAdded,通过LOG_EVENT_FUNC记录日志并调用上层NetdUnsolicitedListener的onInterfaceAdded回调,让Android framework感知新的网络接口出现

这里会回调到上层framework,这样kernel的事件就可以上报到上层

四、 NetdNativeService 分析

重新回到main.cpp分析NetdNativeService相关内容,NetdNativeService::start()函数将NetdNativeService服务发布出去供framework层调用,开始启动native层netd服务。

start函数中BinderService<NetdNativeService>::publish(); 此行函数将NetdNativeService加入到ServiceManager服务中,并建立binder通信, 这样java层就可以通过binder与netd通信。直接通过C层的BinderService向系统添加服务

回到NetdNativeService.h,可以看见,NetdNativeService继承于BinNetd作为服务端提供接口函数的实现(class NetdNativeService : public BinderService<NetdNativeService>, public BnNetd{}),此类包含了众多接口函数,如下:/system/netd/server/NerdNativeService.h。static char const* getServiceName() { return "netd"; },上述函数定义了netd在系统中的服务名字netd。framework层可以getservice获取到INetd的代理类,通过aidl接口调用实现framework层对native层具体功能的使用。

五、 NetdworkManagemenrService 初始化

本节介绍,framework层system server的NetworkManagementservice如何获取NetdNative服务。

该处主要作用是创建并启动一个网络管理服务(NetworkManagementservice),并将该服务注册到系统的服务管理器中。这是一个典型的Android系统服务初始化过程,用于管理系统级别的网络配置和网络功能。其中create的目的是创建NetworkManagementService实例;addService主要是将创建的网络管理服务注册到系统服务管理器中。

通过create方法,初始化NetworkManagementservice,这里deps为new Dependencies()

1)final NetworkManagementService service = new NetworkManagementService(context, deps)

2)调用NetworkManagementService 中的connectNativeNetdService()函数

通过构造方法创建了类对象:初始化了三个参数:

1)mDeps为Dependencies对象,通过调用该对象的getNetd方法可以获取INetd对象,为netd的binder服务的客户端引用;

2)mDaemonHandler为Handler新对象,用于处理消息,在 Listener 收到回调处理请求之后通过 Handler 进行处理,发送对应的消息到消息队列,而其中的 Looper 会处理消息;

3)mNetdUnsolicitedEventListener为NetdUnsolicitedEventListener对象,监听netd中的消息通知进行相应的处理,在这里直接调用了INetd的registerUnsolicitedEventListener方法注册(NetdUnsolicitedEventListener类中定义的函数为onEvent中LOG_EVENT_FUNC回调对应的函数);

mNetdUnsolicitedEventListener是NetdUnsolicitedEventListener对象,继承了INetdUnsolicitedEventListener.Stub接口类,实现了对应的接口,它作为binder服务端,在这里调用了INetd服务的接口registerUnsolicitedEventListener将其进行注册

1)getNetd获取到INetd的代理对象

2)registerUnsolicitedEventListener注册mNetdUnsolicitedEventListener,以接收onEvent相关流程

调用gCtrls类的eventReporter成员的registerUnsolEventListener方法,就是Controllers类的EventReporter成员

EventReporter类接口定义如下

create中的传参new Dependencies为其内部对象,getNetd内部调用NetService的get函数以获取INetd的代理类

用于获取INetd实例的静态方法,具有超时等待机制。当系统中还没有INetd实例可用时,该方法会持续尝试获取,直到超时或者成功获取实例为止。

通过getService获取netd服务的接口实例

参考链接

https://blog.csdn.net/IT_xiao_bai0516/article/details/122309473?spm=1001.2014.3001.5501

相关推荐
阿巴斯甜15 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker15 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952716 小时前
Andorid Google 登录接入文档
android
黄林晴17 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_2 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android