Android源码笔记--网络
Posted ljt2724960661
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android源码笔记--网络相关的知识,希望对你有一定的参考价值。
android网络管理的核心是ConnectivityService 和 NetworkManagerService服务.ConnectivityService主要提供网络连接管理服务,NetworkManagementService主要提供物理网络管理服务。此外还有NetworkPolicyMangerService和NetworkStatsService服务, NetworkPolicyMangerService服务维护各种网络使用策略。NetworkStatsService服务提供查询网络传输统计信息。
1 管理各种网络设备-Netd守护进程
Netd全程是Network Daemon,主要作用是管理各种网络设备。Netd是一个守护进程,通过init进程启动,它在init.rc中的服务定义如下:
service netd /system/bin/netd
socket netd stream 0660 root system
socket dnsproxyd stream 0660 root inet
1.1 Netd的框架
Netd模块的源代码位于目录system/netd中,我们先看看它的入口函数,代码如下:
/system/netd/server/main.cpp
int main()
for (const auto& sock :
DNSPROXYLISTENER_SOCKET_NAME, FwmarkServer::SOCKET_NAME, MDnsSdListener::SOCKET_NAME)
setCloseOnExec(sock);
NetlinkManager *nm = NetlinkManager::Instance();
if (nm == nullptr)
ALOGE("Unable to create NetlinkManager");
exit(1);
;
gCtls = new android::net::Controllers();
gCtls->init();
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;
FwmarkServer fwmarkServer(&gCtls->netCtrl, &gCtls->eventReporter, &gCtls->trafficCtrl);
if (fwmarkServer.startListener())
ALOGE("Unable to start FwmarkServer (%s)", strerror(errno));
exit(1);
// 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);
IPCThreadState::self()->joinThreadPool()
exit(0);
通过NetlinkManager 来监听内核的Netlink Socket,然后读取内核发送的uevent,这些uevent最后会在NetlinkHander对象的onEventO函数中得到处理。
netd.rc文件中netd申明了3个socket,因此,mainO函数中创建了3个FrameworkListenter对象: FwmarkServer、DnsProxyListener和MdnsSdListener,分别监听这3个socket.
1.2 处理net类型的uevent
从内核发送过来的 uevent 最终会在NetlinkHandler 的onEvent()函数中处理,这些uevent是内核监测到硬件或驱动发生了变化后发出的。下面是onEvent()函数的代码:
/system/netd/server/NetlinkHandler.cpp
void NetlinkHandler::onEvent(NetlinkEvent *evt)
const char *subsys = evt->getSubsystem();
if (!subsys)
ALOGW("No subsystem found in netlink event");
return;
if (!strcmp(subsys, "net"))
NetlinkEvent::Action action = evt->getAction();
const char *iface = evt->findParam("INTERFACE");
if ((action == NetlinkEvent::Action::kAdd) ||
(action == NetlinkEvent::Action::kLinkUp) ||
(action == NetlinkEvent::Action::kLinkDown))
const char *ifIndex = evt->findParam("IFINDEX");
long ifaceIndex = parseIfIndex(ifIndex);
if (ifaceIndex)
gCtls->trafficCtrl.addInterface(iface, ifaceIndex);
else
ALOGE("invalid interface index: %s(%s)", iface, ifIndex);
if (action == NetlinkEvent::Action::kAdd)
notifyInterfaceAdded(iface);
else if (action == NetlinkEvent::Action::kRemove)
notifyInterfaceRemoved(iface);
else if (action == NetlinkEvent::Action::kChange)
evt->dump();
notifyInterfaceChanged("nana", true);
else if (action == NetlinkEvent::Action::kLinkUp)
notifyInterfaceLinkChanged(iface, true);
else if (action == NetlinkEvent::Action::kLinkDown)
notifyInterfaceLinkChanged(iface, false);
else if (action == NetlinkEvent::Action::kAddressUpdated ||
action == NetlinkEvent::Action::kAddressRemoved)
const char *address = evt->findParam("ADDRESS");
const char *flags = evt->findParam("FLAGS");
const char *scope = evt->findParam("SCOPE");
const char *ifIndex = evt->findParam("IFINDEX");
char addrstr[INET6_ADDRSTRLEN + strlen("/128")];
strlcpy(addrstr, address, sizeof(addrstr));
char *slash = strchr(addrstr, '/');
if (slash)
*slash = '\\0';
long ifaceIndex = parseIfIndex(ifIndex);
if (!ifaceIndex)
ALOGE("invalid interface index: %s(%s)", iface, ifIndex);
const bool addrUpdated = (action == NetlinkEvent::Action::kAddressUpdated);
if (addrUpdated)
gCtls->netCtrl.addInterfaceAddress(ifaceIndex, address);
else // action == NetlinkEvent::Action::kAddressRemoved
bool shouldDestroy = gCtls->netCtrl.removeInterfaceAddress(ifaceIndex, address);
if (shouldDestroy)
SockDiag sd;
if (sd.open())
int ret = sd.destroySockets(addrstr);
if (ret < 0)
ALOGE("Error destroying sockets: %s", strerror(-ret));
else
ALOGE("Error opening NETLINK_SOCK_DIAG socket: %s", strerror(errno));
// Note: if this interface was deleted, iface is "" and we don't notify.
if (iface && iface[0] && address && flags && scope)
if (addrUpdated)
notifyAddressUpdated(address, iface, std::stoi(flags), std::stoi(scope));
else
notifyAddressRemoved(address, iface, std::stoi(flags), std::stoi(scope));
else if (action == NetlinkEvent::Action::kRdnss)
const char *lifetime = evt->findParam("LIFETIME");
const char *servers = evt->findParam("SERVERS");
if (lifetime && servers)
notifyInterfaceDnsServers(iface, strtol(lifetime, nullptr, 10),
android::base::Split(servers, ","));
else if (action == NetlinkEvent::Action::kRouteUpdated ||
action == NetlinkEvent::Action::kRouteRemoved)
const char *route = evt->findParam("ROUTE");
const char *gateway = evt->findParam("GATEWAY");
const char *iface = evt->findParam("INTERFACE");
if (route && (gateway || iface))
notifyRouteChange((action == NetlinkEvent::Action::kRouteUpdated) ? true : false,
route, (gateway == nullptr) ? "" : gateway,
(iface == nullptr) ? "" : iface);
else if (!strcmp(subsys, "qlog") || !strcmp(subsys, "xt_quota2"))
const char *alertName = evt->findParam("ALERT_NAME");
const char *iface = evt->findParam("INTERFACE");
if (alertName && iface)
notifyQuotaLimitReached(alertName, iface);
else if (!strcmp(subsys, "strict"))
const char *uid = evt->findParam("UID");
const char *hex = evt->findParam("HEX");
if (uid && hex)
notifyStrictCleartext(strtol(uid, nullptr, 10), hex);
else if (!strcmp(subsys, "xt_idletimer"))
const char *label = evt->findParam("INTERFACE");
const char *state = evt->findParam("STATE");
const char *timestamp = evt->findParam("TIME_NS");
const char *uid = evt->findParam("UID");
if (state)
bool isActive = !strcmp("active", state);
int64_t processTimestamp = (timestamp == nullptr) ? 0 : strtoll(timestamp, nullptr, 10);
int intLabel;
// NMS only accepts interface class activity changes with integer labels, and only ever
// creates idletimers with integer labels.
if (android::base::ParseInt(label, &intLabel))
const long reportedUid =
(uid != nullptr && isActive) ? strtol(uid, nullptr, 10) : -1;
notifyInterfaceClassActivityChanged(intLabel, isActive, processTimestamp,
reportedUid);
#if !LOG_NDEBUG
else if (strcmp(subsys, "platform") && strcmp(subsys, "backlight"))
/* It is not a VSYNC or a backlight event */
ALOGV("unexpected event from subsystem %s", subsys);
#endif
onEvent()函数中,对net类的uenvent的处理只是发消息通知Java层(函数中的各种notify函数只是调用CommandListener的接口向Java层发送消息),底层没有进行任何的处理。这里收到的消息有:
NetlinkEvent::kAdd:系统中增加了一种网络interface。
NetlinkEvent::kRemove:系统中移除了一种网络interface。
NetlinkEvent::kChange:系统中某种网络的 interface发生了变化。
NetlinkEvent:kLinkUp:系统中某个网络interface 建立了连接。
NetlinkEvent:kLinkDown:系统中某个网络 interface 断开了连接。
NetlinkEvent::kAddressUpdated:系统中某个网络interface的地址发生了变化。
NetlinkEvent::kAddressRemoved:系统中某个网络interface 的地址被移除了。
NetlinkEvent::kRouteUpdated:系统路由更新。
另外,还有来自流量控制的通知消息和某个网络Interface进入 activity或idle状态的消息。
1.3 处理NMS的命令
NdcDispatcher对象用来处理从 NetworkManagementService中发送的命令。NdcDispatcher类中注册的命令如下:
/system/netd/server/NdcDispatcher.cpp
sp<INetd> NdcDispatcher::mNetd;
sp<IDnsResolver> NdcDispatcher::mDnsResolver;
NdcDispatcher::NdcDispatcher()
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binderNetd = sm->getService(String16("netd"));
sp<IBinder> binderDnsResolver = sm->getService(String16("dnsresolver"));
if ((binderNetd != nullptr) && (binderDnsResolver != nullptr))
NdcDispatcher::mNetd = interface_cast<INetd>(binderNetd);
NdcDispatcher::mDnsResolver = interface_cast<IDnsResolver>(binderDnsResolver);
else
LOG(LOGLEVEL) << "Unable to get binder service";
exit(1);
registerCmd(new InterfaceCmd());
registerCmd(new IpFwdCmd());
registerCmd(new TetherCmd());
registerCmd(new NatCmd());
registerCmd(new BandwidthControlCmd());
registerCmd(new IdletimerControlCmd());
registerCmd(new FirewallCmd());
registerCmd(new ClatdCmd());
registerCmd(new NetworkCommand());
registerCmd(new StrictCmd());
void NdcDispatcher::registerCmd(NdcNetdCommand* cmd)
mCommands.push_back(cmd);
int NdcDispatcher::dispatchCommand(int argc, char** argv)
if (argc >= CMD_ARGS_MAX)
mNdc.sendMsg(500, "Command too long", false);
for (const auto* c : mCommands)
if (c->getCommand() == argv[0])
if (c->runCommand(&mNdc, argc, argv))
mNdc.sendMsg(500, "Handler error", true);
return 0;
mNdc.sendMsg(500, "Command not recognized", false);
return 0;
其中:
InterfaceCmd对象用来处理各种网络Interface相关的命令,例如,添加、删除
IpFwdCmd对象用来处理IP转发的命令,包括status、enable和disable命令;
TetherCmd对象用来处理网络共享的命令;
NatCmd对象用来处理带宽控制的命令;
BandwidthControlCmd 用来处理带宽控制的命令;
IdletimerControlCmd用来处理设置监听网络接口空闲的命令;
FirewallCmd 用来处理设置防火墙的命令;
ClatdCmd用来处理启动或停止 clatd的命令。
NetworkCommand 用来处理解析网络地址的命令,包括设置dns服务器的地址;
1.4 DNS服务代理
DnsProxyListener对象实现了DNS服务的代理功能,它注册了以下的命令:
DnsProxyListener::DnsProxyListener() : FrameworkListener(SOCKET_NAME)
registerCmd(new GetAddrInfoCmd());
registerCmd(new GetHostByAddrCmd());
registerCmd(new GetHostByNameCmd());
registerCmd(new ResNSendCommand());
registerCmd(new GetDnsNetIdCommand());
说明:
GetAddrInfoCmd 命令用来完成主机名到IP地址解析。
GetHostByAddrCmd 命令用来完成从IP地址到主机名的解析。
GetHostByNameCmd 命令通过主机名获得主机信息。
1.5 MDnsSdListener的作用-与守护进程进行交互
/system/netd/server/MDnsSdListener.cpp
MDnsSdListener::MDnsSdListener() : FrameworkListener(SOCKET_NAME, true)
Monitor *m = new Monitor();
registerCmd(new Handler(m, this));
MDnsSdListener 中的命令主要作用是和mdsnd守护进程进行交互。包括启动和停止 mdsnd守护进程,通过mdsnd来解析一些服务的地址等。
以上是关于Android源码笔记--网络的主要内容,如果未能解决你的问题,请参考以下文章