Android 4.1 Netd详细分析(四)代码分析2

来源:互联网 发布:kali 访问windows共享 编辑:程序博客网 时间:2024/05/18 02:22
我们按照main函数代码的执行顺序,首先实例化NetlinkManager。接下来代码如下。
[cpp] view plaincopy
  1.    if (!(nm = NetlinkManager::Instance())) {//实例化对象nm  
  2.        ALOGE("Unable to create NetlinkManager");  
  3.        exit(1);  
  4.    };  
  5.   
  6.    cl = new CommandListener();//实例化对象cl  
  7.   
  8. // 将nm的mBroadcaster设置为cl  
  9. // 这样nm就可以通过cl对象的socket进行广播将消息提交给framework层  
  10.    nm->setBroadcaster((SocketListener *) cl);  
  11.   
  12.    if (nm->start()) {//nm开始start线程  
  13.        ALOGE("Unable to start NetlinkManager (%s)", strerror(errno));  
  14.        exit(1);  
  15.    }  
  16.    

 

首先进行 NetlinkManager 的实例化。从 NetlinkManager.cpp 中可以查看到实例化的内容如下 ,其中 mBroadcaster 的类型是 SocketListener*。

[cpp] view plaincopy
  1. NetlinkManager *NetlinkManager::Instance() {  
  2.     if (!sInstance)  
  3.         sInstance = new NetlinkManager();  
  4.     return sInstance;  
  5. }  
  6.   
  7. NetlinkManager::NetlinkManager() {  
  8.     mBroadcaster = NULL;  
  9. }  

接下来实例化 CommandListener 并将 nm 的 setBroadcaster 进行赋值,通过这个步骤操作,可以使 nm 调用到 cl 的 socket 进行广播,意义是将 nm 的处理结果通过内部广播提交给Framework,在后面将详细介绍。

 

而后 nm 调用了它的 start()方法,如下。 函数创建了三个监听线程,根据 setupSocket 参数的不同可以限定监听socket 的监听的内核模块事件,并分别start。

[cpp] view plaincopy
  1. ////////////////// Netlinkmanager.start() /////////////////////////////////  
  2. int NetlinkManager::start() {  
  3.    //监听线程 1:   
  4.     // family : NETLINK_KOBJECT_UEVENT  
  5.    // group : 0xffffffff  (all)  
  6.     // format :NETLINK_FORMAT_ASCII  
  7.     if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT,  
  8.          0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII)) == NULL) {  
  9.         return -1;  
  10.     }  
  11.     //监听线程2 :  与内核通信模块-> 路由表  
  12.     // family : NETLINK_ROUTE  
  13.     //  group : RTMGRP_LINK   (RouTeMsg GRouP)  
  14.     // format : NETLINK_FORMAT_BINARY   
  15.     if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE, RTMGRP_LINK,  
  16.          NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) {  
  17.         return -1;  
  18.     }  
  19.     //监听线程 3:  
  20.     // family : NETLINK_NFLOG  
  21.     //  group : NFLOG_QUOTA_GROUP   
  22.     // format : NETLINK_FORMAT_BINARY  
  23.     if ((mQuotaHandler = setupSocket(&mQuotaSock, NETLINK_NFLOG,  
  24.         NFLOG_QUOTA_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) {  
  25.         ALOGE("Unable to open quota2 logging socket");  
  26.         // TODO: return -1 once the emulator gets a new kernel.  
  27.     }  
  28.   
  29.     return 0;  
  30. }  

 

如下式setupSocket()函数,创建socket,设置属性,并start线程开始监听,函数的返回值为 Netlinkhandler 类型。

[cpp] view plaincopy
  1. //参数说明  
  2. // sock          : 返回的socket表示符  
  3. // netlinkFamily : 指定与那写内核模块通信  
  4. // groups        : 多播组掩码  
  5. // format        : 创建NetlinkHandler指定的参数,指定对evt的解码方式  
  6. NetlinkHandler *NetlinkManager::setupSocket(int *sock, int netlinkFamily,  
  7.     int groups, int format) {  
  8.   
  9.     struct sockaddr_nl nladdr;  
  10.     int sz = 64 * 1024;  
  11.     int on = 1;  
  12.   
  13.     memset(&nladdr, 0, sizeof(nladdr));  
  14.     nladdr.nl_family = AF_NETLINK;  
  15.     nladdr.nl_pid = getpid();  
  16.     nladdr.nl_groups = groups;      //多播组  
  17.     //  
  18.     //创建socket  
  19.     //  
  20.     if ((*sock = socket(PF_NETLINK, SOCK_DGRAM, netlinkFamily)) < 0) {  
  21.         ALOGE("Unable to create netlink socket: %s", strerror(errno));  
  22.         return NULL;  
  23.     }  
  24.   
  25.     //recive buffer   
  26.     //空间大小为64K的buff  
  27.     if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {  
  28.         ALOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno));  
  29.         close(*sock);  
  30.         return NULL;  
  31.     }  
  32.   
  33.     //pass credentials opt  
  34.     //关于credentials(证书)      
  35.     if (setsockopt(*sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {  
  36.         SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno));  
  37.         close(*sock);  
  38.         return NULL;  
  39.     }  
  40.     //  
  41.     //bind函数,将socket绑定唯一的 属性&地址&port……     
  42.     //(因sockaddr_nl不同而不同,即因创建socket时属性)  
  43.     if (bind(*sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {  
  44.         ALOGE("Unable to bind netlink socket: %s", strerror(errno));  
  45.         close(*sock);  
  46.         return NULL;  
  47.     }  
  48.     //NetlinkHandler.start()  
  49.     //继承关系  
  50.     //NetlinkHandler -> NetlinkListener -> SocketListener -> start()  
  51.     NetlinkHandler *handler = new NetlinkHandler(this, *sock, format);  
  52.     if (handler->start()) {//*****************handler -> start  
  53.         ALOGE("Unable to start NetlinkHandler: %s", strerror(errno));  
  54.         close(*sock);  
  55.         return NULL;  
  56.     }  
  57.   
  58.     return handler;  
  59. }  

 

期间还经过 socket()创建 socket,setsockopt()设置基本属性、buffer、credentials、bind()函数。最后调用 NetlinkHandler 的 start()方法。期间的继承关系,NetlinkHandler
→NetlinkListener → SocketListener。而 NetlinkListener 中并没有 startListener(),实在SocketListener 中才存在该接口。

 
由此进入了 Socket 公共库中,这部分代码为很多种系统调配用,也提供了很多接口功能,比如Vold 也使用了与 Netd 极为相似的结构。

相关路径:

/system/core/include/sysutils
/system/core/libsysutils/src    

 

[cpp] view plaincopy
  1. int SocketListener::startListener() {  
  2.   
  3.     if (!mSocketName && mSock == -1) {  
  4.         SLOGE("Failed to start unbound listener");  
  5.         errno = EINVAL;  
  6.         return -1;  
  7.     } else if (mSocketName) {  
  8.         if ((mSock = android_get_control_socket(mSocketName)) < 0) {  
  9.             SLOGE("Obtaining file descriptor socket '%s' failed: %s",  
  10.                  mSocketName, strerror(errno));  
  11.             return -1;  
  12.   
  13.         }  
  14.         SLOGV("got mSock = %d for %s", mSock, mSocketName);  
  15.     }  
  16.       
  17.     if (mListen && listen(mSock, 4) < 0) {   //有链接(tcp)  
  18.         SLOGE("Unable to listen on socket (%s)", strerror(errno));  
  19.         return -1;  
  20.     } else if (!mListen)            //无链接(udp)  
  21.         mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));  
  22.   
  23.     if (pipe(mCtrlPipe)) {            
  24.         SLOGE("pipe failed (%s)", strerror(errno));  
  25.         return -1;  
  26.     }  
  27.   
  28.     if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {  
  29.         SLOGE("pthread_create (%s)", strerror(errno));  
  30.         return -1;  
  31.     }  
  32.   
  33.     return 0;  
  34. }  
  35.   
  36. int SocketListener::stopListener() {  
  37.     char c = 0;  
  38.     int  rc;  
  39.   
  40.     rc = TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &c, 1));  
  41.     if (rc != 1) {  
  42.         SLOGE("Error writing to control pipe (%s)", strerror(errno));  
  43.         return -1;  
  44.     }  
  45.   
  46.     void *ret;  
  47.     if (pthread_join(mThread, &ret)) {  
  48.         SLOGE("Error joining to listener thread (%s)", strerror(errno));  
  49.         return -1;  
  50.     }  
  51.     close(mCtrlPipe[0]);  
  52.     close(mCtrlPipe[1]);  
  53.     mCtrlPipe[0] = -1;  
  54.     mCtrlPipe[1] = -1;  
  55.   
  56.     if (mSocketName && mSock > -1) {  
  57.         close(mSock);  
  58.         mSock = -1;  
  59.     }  
  60.   
  61.     SocketClientCollection::iterator it;  
  62.     for (it = mClients->begin(); it != mClients->end();) {  
  63.         delete (*it);  
  64.         it = mClients->erase(it);  
  65.     }  
  66.     return 0;  
  67. }  

 

如上调用 startListener(),这里在监听 Kernel 层中,使用的是无链接状态(udp)的 socket 因为该部分 socket 只涉及到单向的通信,而后调用 pthread_create 函数创建新的线程,并将 this 指针传递给它,正式的启动线程监听。

[cpp] view plaincopy
  1. void *SocketListener::threadStart(void *obj) {  
  2.     SocketListener *me = reinterpret_cast<SocketListener *>(obj);  
  3.  //获得上层  
  4.  //无关类型转换,获得完全相同的比特位    
  5.     me->runListener();  
  6.     pthread_exit(NULL);  
  7.     return NULL;  
  8. }  

 

runListener()才是真正的处理函数,使用了 fd_set 结构,使用了 select 函数,用于判断监听的 kernel 相关部分是否有 event 发出,如果有,则调用 onDataAvailable 函数进行处理(如下)。该函数主要功能是对于 event 进行解码、判断、调用处理函数。该函数在 SocketListener 中为纯虚函数,只是提供了接口,根据具体继承关系、使用 socket 类型(有链接、无链接、socketpair),再做不同的处理,由于现分析是通过 NetlinkListener 进行的调用。

[cpp] view plaincopy
  1. void SocketListener::runListener() {  
  2.   
  3.     SocketClientCollection *pendingList = new SocketClientCollection();  
  4.   
  5.     while(1) {  
  6.         SocketClientCollection::iterator it;  
  7.         fd_set read_fds; //使用了fd_set  
  8.         int rc = 0;  
  9.         int max = -1;  
  10.   
  11.         FD_ZERO(&read_fds);  
  12.  //mListener用于判断有链接(TCP)or无链接(UDP)  
  13.         if (mListen) {  
  14.             max = mSock;  
  15.             FD_SET(mSock, &read_fds);  
  16.         }  
  17.    
  18.         FD_SET(mCtrlPipe[0], &read_fds);  
  19.         if (mCtrlPipe[0] > max)  
  20.             max = mCtrlPipe[0];  
  21.    
  22.  //将链接socket压入mClients队列  
  23.         pthread_mutex_lock(&mClientsLock);  
  24.         for (it = mClients->begin(); it != mClients->end(); ++it) {  
  25.             int fd = (*it)->getSocket();  
  26.             FD_SET(fd, &read_fds);  
  27.             if (fd > max)  
  28.                 max = fd;  
  29.         }  
  30.         pthread_mutex_unlock(&mClientsLock);  
  31.         SLOGV("mListen=%d, max=%d, mSocketName=%s", mListen, max, mSocketName);  
  32.  //select函数  
  33.  //返回值:fd中为1的bit个数即满足条件的socket个数  
  34.         if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {  
  35.             if (errno == EINTR)  
  36.                 continue;  
  37.             SLOGE("select failed (%s) mListen=%d, max=%d", strerror(errno), mListen, max);  
  38.             sleep(1);  
  39.             continue;  //  < 0 出错  
  40.         } else if (!rc)  // == 0 没有可都数据  
  41.             continue;  
  42.    
  43.  //********有数据************  
  44.   
  45.         if (FD_ISSET(mCtrlPipe[0], &read_fds))  
  46.             break;  
  47.    
  48.  //TCP并且监听端口状态变可读  
  49.         if (mListen && FD_ISSET(mSock, &read_fds)) {  
  50.             struct sockaddr addr;  
  51.             socklen_t alen;  
  52.             int c;  
  53.   
  54.             do {  
  55.                 alen = sizeof(addr);  
  56.                 c = accept(mSock, &addr, &alen);//accept函数,阻塞  
  57.                 SLOGV("%s got %d from accept", mSocketName, c);  
  58.             } while (c < 0 && errno == EINTR);  
  59.             if (c < 0) {  
  60.                 SLOGE("accept failed (%s)", strerror(errno));  
  61.                 sleep(1);  
  62.                 continue;  
  63.             }  
  64.   //将链接socket套接字加入mClients  
  65.             pthread_mutex_lock(&mClientsLock);  
  66.             mClients->push_back(new SocketClient(c, true, mUseCmdNum));  
  67.             pthread_mutex_unlock(&mClientsLock);  
  68.         }  
  69.   
  70.         /* Add all active clients to the pending list first */  
  71.  //全部加入到pending中  
  72.         pendingList->clear();  
  73.         pthread_mutex_lock(&mClientsLock);  
  74.         for (it = mClients->begin(); it != mClients->end(); ++it) {  
  75.             int fd = (*it)->getSocket();  
  76.             if (FD_ISSET(fd, &read_fds)) {  
  77.                 pendingList->push_back(*it);  
  78.             }  
  79.         }  
  80.         pthread_mutex_unlock(&mClientsLock);  
  81.   
  82.         /* Process the pending list, since it is owned by the thread, 
  83.          * there is no need to lock it */  
  84.   
  85.         while (!pendingList->empty()) {  
  86.             /* Pop the first item from the list */  
  87.             it = pendingList->begin();  
  88.             SocketClient* c = *it;  
  89.             pendingList->erase(it);  
  90.             /* Process it, if false is returned and our sockets are 
  91.              * connection-based, remove and destroy it */  
  92.   
  93.             if (!onDataAvailable(c) && mListen) { //onDataAvailable函数解码成功后  
  94.        //在netlinkListener(UDP)或者   
  95.        //frameworkListener中  
  96.        //返回TRUE  
  97.                 /* Remove the client from our array */  
  98.                 SLOGV("going to zap %d for %s", c->getSocket(), mSocketName);  
  99.                 pthread_mutex_lock(&mClientsLock);  
  100.                 for (it = mClients->begin(); it != mClients->end(); ++it) {  
  101.                     if (*it == c) {  
  102.                         mClients->erase(it);  //删除掉本SocketClient因为处理已经完成  
  103.                         break;  
  104.                     }  
  105.                 }  
  106.                 pthread_mutex_unlock(&mClientsLock);  
  107.                 /* Remove our reference to the client */  
  108.   //删除掉它的属性  
  109.                 c->decRef();   
  110.             }  
  111.         }//end of while(!pendingList->empty())  
  112.     }  
  113.     delete pendingList;  
  114. }  


至此从 netd/Netlinkmanager 到公共库中的具体监听socket 的实现,自上而下的监听就算成了,该部分实现了 Kernel 部分与 Netd 的联系的建立。上面调用的 NetlinkListener 中的 onDataAvaliable(如下)。而后在 onDataAvaiable()中,通过调用 NetlinkEvent 中的 decode 方法将受到的 event 按照要求的格式进行解码,解码成功后将调用 onEvent 方法进行处理,这里的 onEvent 函数也是纯虚函数,只做借口具体的实现在,netd/NetlinkHandler.cpp 中。

[cpp] view plaincopy
  1. ////////////////  NetlinnkListener.onDataAvailable()  /////////////////////  
  2. bool NetlinkListener::onDataAvailable(SocketClient *cli)  
  3. {  
  4.     int socket = cli->getSocket();  
  5.     ssize_t count;  
  6.     uid_t uid = -1;  
  7.       
  8.     count = TEMP_FAILURE_RETRY(uevent_kernel_multicast_uid_recv(      //多播接受  
  9.                                        socket, mBuffer, sizeof(mBuffer), &uid));  
  10.     if (count < 0) {  
  11.         if (uid > 0)  
  12.             LOG_EVENT_INT(65537, uid);  
  13.         SLOGE("recvmsg failed (%s)", strerror(errno));  
  14.         return false;  
  15.     }  
  16.     //decode解码成功返回true  
  17.     NetlinkEvent *evt = new NetlinkEvent();  
  18.     if (!evt->decode(mBuffer, count, mFormat)) {  
  19.         SLOGE("Error decoding NetlinkEvent");  
  20.     } else {  
  21.     //纯虚函数  
  22.         onEvent(evt);  
  23.     }  
  24.   
  25.     delete evt;  
  26.     return true;  
  27. }  


至此,处理流程又回到了 netd 部分(),并且得到了解码成字符串形式的来自 Kernel 的 event,接下来开始在 netd 部分进行处理,并将处理结果提交给 Framework 层。onEvent 函数根据不同的 event 进行选择,调用相应的处理函数如下。

[cpp] view plaincopy
  1. // ************ NetlinkEvent中定义 **************  
  2. // const int NetlinkEvent::NlActionUnknown = 0;  
  3. // const int NetlinkEvent::NlActionAdd = 1;  
  4. // const int NetlinkEvent::NlActionRemove = 2;  
  5. // const int NetlinkEvent::NlActionChange = 3;  
  6. // const int NetlinkEvent::NlActionLinkUp = 4;  
  7. // const int NetlinkEvent::NlActionLinkDown = 5;  
  8. // *********************************************  
  9. void NetlinkHandler::onEvent(NetlinkEvent *evt) {  
  10. const char *subsys = evt->getSubsystem();  
  11. if (!subsys) {  
  12. ALOGW("No subsystem found in netlink event");  
  13. return;  
  14. }  
  15. //主要处理的是net部分  
  16. if (!strcmp(subsys, "net")) {  
  17. int action = evt->getAction();  
  18. const char *iface = evt->findParam("INTERFACE");  
  19.   
  20. if (action == evt->NlActionAdd) {  
  21. notifyInterfaceAdded(iface);  
  22. else if (action == evt->NlActionRemove) {  
  23. notifyInterfaceRemoved(iface);  
  24. else if (action == evt->NlActionChange) {  
  25. evt->dump();  
  26. notifyInterfaceChanged("nana"true);  
  27. else if (action == evt->NlActionLinkUp) {  
  28. notifyInterfaceLinkChanged(iface, true);  
  29. else if (action == evt->NlActionLinkDown) {  
  30. notifyInterfaceLinkChanged(iface, false);  
  31. }  
  32.   
  33. }//end of “net”  
  34. else if (!strcmp(subsys, "qlog")) {  
  35. const char *alertName = evt->findParam("ALERT_NAME");  
  36. const char *iface = evt->findParam("INTERFACE");  
  37. notifyQuotaLimitReached(alertName, iface);  
  38.   
  39. else if (!strcmp(subsys, "xt_idletimer")) {  
  40. int action = evt->getAction();  
  41. const char *iface = evt->findParam("INTERFACE");  
  42. const char *state = evt->findParam("STATE");  
  43. if (state)  
  44. notifyInterfaceActivity(iface, !strcmp("active", state));  
  45.   
  46. #if !LOG_NDEBUG //uevent 忽略掉了?  
  47. //网络管理涉及,黒屏 & 断开/链接 wifi保持连接状态~所以也要捕捉uevent  
  48. else if (strcmp(subsys, "platform") && strcmp(subsys, "backlight")) {  
  49. /* It is not a VSYNC or a backlight event */  
  50. ALOGV("unexpected event from subsystem %s", subsys);  
  51. #endif  
  52. }  
  53. }  

一般从内核发出的 event 都做状态报告,查拔事件等,一般主要目的是向上层发报反馈。如下调用了 mNm 的 getBroadcaster 的 sendBroadcast 方法,该方法即为前文中主函数提到的,nm 将mBroadcaster 用 cl 进行赋值的目的。直接将相应的操作码(ResponseCode 类中全部为操作码)连带消息字符串发送给 Framework 层。此时 cl 应该已经通过 startlistener 方法与 Framework 层建立联系。

  至此,捕捉内核event,并向上层反馈的基本流程就算分析完了,那么kernel-netd-framework的‘一半’我们就算了解了。

 

 

 

0 0
原创粉丝点击