提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
一、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_NETFILTER消息))。
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