Android 4.1 Netd详细分析(三)代码分析1

 

个人邮箱:xiaokeweng@gmail.com

       接下来开始从代码分析,按照从下至上的顺序来分析,从native层向framework层过渡,Android的各个层之间严格按照软件工程原理的低耦合要求.

#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 的桥梁。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值