個人郵箱:xiaokeweng@gmail.com
接下來開始從程式碼分析,按照從下至上的順序來分析,從native層向framework層過渡,Android的各個層之間嚴格按照軟體工程原理的低耦合要求,關於Android 的系統架構可以參考附錄:link~(待完善)
在Netd部分使用到得Socket通訊,關於Android內部的IPC機制可以參考附錄:link~(待完善)
===================================================================
#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 的橋樑。