Android2.2 Vold 分析-(二)---Vold 中 Netlink事件通信机制分析

Android2.2 Vold 分析-2---20110105

Vold 中 Netlink事件通信机制分析

NetlinkHandler的成员函数start()会调用SocketListener::startListen()

在system/vold/main.cpp main()函数中调用nl->start(),就是调用int NetlinkManager::start() 函数,该函数主要功能:
    (1). 创建NETLINK socket
    (2). 构建NetlinkHandler对象,并通过其成员函数start()调用SocketListener::startListen();
分析如下:
int NetlinkManager::start() {
    struct sockaddr_nl nladdr;
    int sz = 64 * 1024;

    memset(&nladdr, 0, sizeof(nladdr));
    nladdr.nl_family = AF_NETLINK;
    nladdr.nl_pid = getpid();
    nladdr.nl_groups = 0xffffffff;

    if ((mSock = socket(PF_NETLINK, SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {}
    if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) { }
    if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {}

    mHandler = new NetlinkHandler(mSock);
    if (mHandler->start()) {  }
    return 0;
}
调用startListen,mSock前面创建,
int SocketListener::startListener() {

    if (!mSocketName && mSock == -1) { }
    else if (mSocketName) {
        if ((mSock = android_get_control_socket(mSocketName)) < 0) { }
    }
    if (mListen && listen(mSock, 4) < 0) {} //监听套接字执行这一部分
     else if (!mListen)   //如果非监听套接字(TCP有监听套接字,和数据交换套接字,UDP只有数据交换套接字),Netlink为UDP,所以执行这一部分;
         mClients->push_back(new SocketClient(mSock));          //直接执行这一行,将NetLink的socket添加到mClient容器中;
    if (pipe(mCtrlPipe)) { }
    if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {  } //启动新的线程,这里的this 指的是NetlinkHandler的对象 如下:
    return 0;
}
线程函数:
void *SocketListener::threadStart(void *obj) {
    SocketListener *me = reinterpret_cast<SocketListener *>(obj);  //将NetlinkHandler对象强制转换为SocketListener类型对象,调用其runListener函数
    me->runListener();
 }
线程真正执行的函数:mListen成员用来判定是否监听套接字

Netlink套接字属于udp套接字,非监听套接字,该函数的主要功能体现在,如果该套接字有数据到来,就调用相关函数读取数据。

void SocketListener::runListener() {
    while(1) {  //无线循环,一直监听
        SocketClientCollection::iterator it;
        fd_set read_fds;
        int rc = 0;
        int max = 0;
        FD_ZERO(&read_fds);  //清空文件描述符集read_fds
        if (mListen) {
            max = mSock;
            FD_SET(mSock, &read_fds);  //添加文件描述符到文件描述符集read_fds
        }

        FD_SET(mCtrlPipe[0], &read_fds);
        if (mCtrlPipe[0] > max)
            max = mCtrlPipe[0];

        pthread_mutex_lock(&mClientsLock);
        for (it = mClients->begin(); it != mClients->end(); ++it) {   //将容器nClient中的sockets添加到文件描述符集read_fds
            FD_SET((*it)->getSocket(), &read_fds);    
            if ((*it)->getSocket() > max)
                max = (*it)->getSocket();
        }
        pthread_mutex_unlock(&mClientsLock);

        if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {   //等待文件描述符中某一文件描述符或者说socket有数据到来
             continue;
        } else if (!rc)
            continue;

        if (FD_ISSET(mCtrlPipe[0], &read_fds))     //管道
            break;
        if (mListen && FD_ISSET(mSock, &read_fds)) {  //监听套接字
            struct sockaddr addr;
            socklen_t alen = sizeof(addr);
            int c;

            if ((c = accept(mSock, &addr, &alen)) < 0) {    //接收链接请求,建立连接,如果成功c即为建立链接后的数据交换套接字,将其添加到mClient器;
                continue;
            }
            pthread_mutex_lock(&mClientsLock);
            mClients->push_back(new SocketClient(c));
            pthread_mutex_unlock(&mClientsLock);
        }

        do {   //非监听套接字处理
            pthread_mutex_lock(&mClientsLock);
            for (it = mClients->begin(); it != mClients->end(); ++it) {
                int fd = (*it)->getSocket();
                if (FD_ISSET(fd, &read_fds)) {
                    pthread_mutex_unlock(&mClientsLock);
                    if (!onDataAvailable(*it)) {    //调用相应的数据读取函数,读取数据
                        close(fd);
                        pthread_mutex_lock(&mClientsLock);
                        delete *it;
                        it = mClients->erase(it);
                        pthread_mutex_unlock(&mClientsLock);
                    }
                    FD_CLR(fd, &read_fds);
                    continue;
                }
            }
            pthread_mutex_unlock(&mClientsLock);
        } while (0);
    }
}

分析函数: onDataAvailable(*it)
onDataAvailable是在类SocketListener中定义的纯虚函数,在Android2.2中共有五个类继承该类,并对函数onDataAvailable进行了实现,分别是:
    DhcpListener(system/core/nexus)、
    FrameworkListener(system/core/libsysutils/src)、
    NetlinkListener(system/core/libsysutils/src)、
    SupplicantListener(system/core/nexus)、
    TiwlanEventListener(system/core/nexus);

针对Netlink创建的套接字,是由NetlinkHandler对象调用的startListen函数,并开启的相关线程,而且NetlinkHandler继承了NetlinkListener,
所以此处调用的是NetlinkListener类的成员函数onDataAvailable;
system/core/libsysutils/src/NetlinkListener.cpp
bool NetlinkListener::onDataAvailable(SocketClient *cli)
{
    int socket = cli->getSocket();
    int count;

    if ((count = recv(socket, mBuffer, sizeof(mBuffer), 0)) < 0) {  } //读取数据

    NetlinkEvent *evt = new NetlinkEvent();  
    if (!evt->decode(mBuffer, count)) {  }

    onEvent(evt);   //NetlinkListener类定义了纯虚函数,其子类NetlinkHandler对其进行了实现,所以此处调用子类NetlinkHandler的onEvent函数;
out:
    delete evt;
    return true;
}

onEvent 函数分析:
system/vold/NetlinkHandler.cpp

void NetlinkHandler::onEvent(NetlinkEvent *evt) {
    VolumeManager *vm = VolumeManager::Instance();
    const char *subsys = evt->getSubsystem();

    if (!subsys) {
        SLOGW("No subsystem found in netlink event");
        return;
    }

    if (!strcmp(subsys, "block")) {
        vm->handleBlockEvent(evt);  
    } else if (!strcmp(subsys, "switch")) {
        vm->handleSwitchEvent(evt);
    } else if (!strcmp(subsys, "battery")) {
    } else if (!strcmp(subsys, "power_supply")) {
    }
}

这下子又回到了vold进程中,到此在android中vold相关部分的Netlink event传递机制分析完成,下一步该分析真正的vold管理部分了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值