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)) { // 执行command SLOGW("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来执行操作