Android 4.1 Netd详细分析(三)代码分析1分类:
Android2012-11-02 11:26 2386人阅读
评论(0)
举报个人邮箱:xiaokeweng@gmail.com
接下来开始从代码分析,按照从下至上的顺序来分析,从native层向framework层过渡,Android的各个层之间严格按照软件工程原理的低耦合要求.
[cpp]
view plaincopy#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <dirent.h>
#define LOG_TAG "Netd"
#include "cutils/log.h"
#include "CommandListener.h"
#include "NetlinkManager.h"
#include "DnsProxyListener.h"
#include "MDnsSdListener.h"
static void coldboot(const char *path);
static void sigchld_handler(int sig);
static void blockSigpipe();
int main() {
/********************************************************
*以下两个为函数主要使用的类
*CommandListener :监听 framework 层的命令,并调用本类中注册的处理函数,并将处理结果返回
*NetLinkManager :管理 kernel 层相关的 event,将收到收到的信息提交给 framework 层
********************************************************/
CommandListener *cl;
NetlinkManager *nm;
/********************************************************
* 这两个可以各自理解为单独的工作模块,相对上面的类更加简单。
* DnsProxyListener :DNS 解析,通过系统库函数 getaddrinfo,并将解析结果反馈给 framework 层
* MDnsSdListener :Muliticast-DNS Server Descript 利用局域网其他对象解析
********************************************************/
DnsProxyListener *dpl;
MDnsSdListener *mdnsl;
ALOGI("Netd 1.0 starting");
// signal(SIGCHLD, sigchld_handler);
blockSigpipe(); //禁用Sigpipe
if (!(nm = NetlinkManager::Instance())) { //实例化nm
ALOGE("Unable to create NetlinkManager");
exit(1);
};
/*******************************************************
* nm->setBroadcaster((SocketListener *) cl)
* setBroadcaster函数将NetlinkManager的成员变量mBroadcaster设置成cl,这两个变量都是
* ScoketListener的指针类型,命令执行广播函数,就会调用这个SocketListener的指针来调用
* SocketListener类的广播函数* 因为:继承关系:
* CommandListener(子类)-->FrameworkListener()-->SocketListener(父类)*******************************************************/
cl = new CommandListener(); //实例化cl
nm->setBroadcaster((SocketListener *) cl); //关联nm和cl这样nm就可以通过方法
//广播消息来回复给framework
/**************************************************
* 使用了 Netlink socket 是用于实现用户进程与内核进程通信的 IPC,
* 下面的 start()就是开启监听内核的线程。
*************************************************/
if (nm->start()) {
ALOGE("Unable to start NetlinkManager (%s)", strerror(errno));
exit(1); }
/**************************************************
* 关于DnsProxyListener/MdnsSdListener会在后面单独详细
* 各自的原理同CommandListener+NetlinkManager两个组成的系统
**************************************************/
// Set local DNS mode, to prevent bionic from proxying(自动代理)
// back to this service, recursively.(递归)
// DnsProxyListener -> FrameworkListrner -> SocketListener
setenv("ANDROID_DNS_MODE", "local", 1); //设置为本地模式,是一个全局变量
//DNS
dpl = new DnsProxyListener();
if (dpl->startListener()) {
ALOGE("Unable to start DnsProxyListener (%s)", strerror(errno));
exit(1);
}
//multicast_DNS_server_descript_listener //多播DNS守护进程
//内网没有DNS服务器时,出现此组播
mdnsl = new MDnsSdListener();
if (mdnsl->startListener()) {
ALOGE("Unable to start MDnsSdListener (%s)", strerror(errno));
exit(1);
}
/************************************************
* cl 开启线程,监听 framework 层下发的命令,并调用相关函数处理
*********************************************** */
if (cl->startListener()) {
ALOGE("Unable to start CommandListener (%s)", strerror(errno));
exit(1);
}
// 成为守护进程
while(1) {
sleep(1000);
}
ALOGI("Netd exiting");
exit(0);
}
///*********打杂函数**************//
// 实际还真没看到打杂的意义/作用是什么……
static void do_coldboot(DIR *d, int lvl)
{
struct dirent *de;
int dfd, fd;
dfd = dirfd(d);
fd = openat(dfd, "uevent", O_WRONLY);
if(fd >= 0) {
write(fd, "add\n", 4);
close(fd);
}
while((de = readdir(d))) {
DIR *d2;
if (de->d_name[0] == '.')
continue;
if (de->d_type != DT_DIR && lvl > 0)
continue;
fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
if(fd < 0)
continue;
d2 = fdopendir(fd);
if(d2 == 0)
close(fd);
else {
do_coldboot(d2, lvl + 1);
closedir(d2);
}
}
}
static void coldboot(const char *path)
{
DIR *d = opendir(path);
if(d) {
do_coldboot(d, 0);
closedir(d);
}
}
static void sigchld_handler(int sig) {
pid_t pid = wait(NULL);
ALOGD("Child process %d exited", pid);
}
static void blockSigpipe()
{
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGPIPE);
if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
ALOGW("WARNING: SIGPIPE not blocked\n");
}
至此,按照 main 函数的流程进行分析。
首先如上图,系统的部分主干关系图,系统可以按照功能和相关性分为三大部分,DnsProxyLis-
tener,MDnsSdListener,和 CommandListener + NetlinkManager 三大部分,每个部分都能够利用内
部 socket 和独立线程,接收到 Framework 层的命令,系统调用操作 Kernel 层,并回复 Framework 反
馈,可是说 Netd 充当了 Framework 与 kernel 的桥梁。