个人邮箱: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. TabActivity子类中处理返回键事件
  2. android showSoftInput方法调用软键盘不显示
  3. Android(安卓)webView与JavaScript的交互
  4. Android函数响应式编程——必学的RxJava组合操作符startWith、me
  5. Android,一个函数实现指南针
  6. android-market-api
  7. android用户界面-组件Widget-网络视图WebView
  8. Android(安卓)进阶——Framework 核心四大组件之跨进程共享组件C
  9. Android(安卓)双开沙箱 VirtualApp 源码分析(四)启动插件 Service

随机推荐

  1. 抽象类与接口、后期静态绑定与魔术方法简
  2. HTTP的恋爱史
  3. 23 个非常实用的 Shell 拿来就用脚本实例
  4. dblink不稳定造成 cursor: pin s wait on
  5. 新人和老人关于数据思维的50个区别
  6. ORA-15040 ora-15017ASM磁盘无法挂载故障
  7. 面试官常考的 21 条 Linux 命令
  8. Go:变量声明,字符类型
  9. lob字段的direct path read等待导致的性
  10. php多维数组创建及遍历