Vold之NetlinkManager2

总结:NetlinkManager是直接接收Kernel消息的模块,其从kernel接收Uevent事件,然后转换成一个NetlinkEvent对象,最后调用VolumeManager的处理函数继续后续操作。NetLinkEvent以及Uevent存在的目的就是告知上层底层发生的一切。

1、system/vold/NetlinkManager.cpp

由之前的了解,可知,在系统启动后,NetlinkManager会做以下事情:

1、nm->setBroadcaster((SocketListener *) cl);

2、if (nm->start()) {
        SLOGE("Unable to start NetlinkManager (%s)", strerror(errno));
        exit(1);
    }
3、coldboot("/sys/block");


2.1、setBroadcaster方法,获得CommandListener的句柄

void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
2、2:start方法:

首先初始化接收底层消息的socket,并为其开辟内存空间。

struct sockaddr_nl nladdr;
    int sz = 64 * 1024;
    int on = 1;

    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) {
        SLOGE("Unable to create uevent socket: %s", strerror(errno));
        return -1;
    }
执行bind操作:

if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
        SLOGE("Unable to bind uevent socket: %s", strerror(errno));
        goto out;
    }

创建NetlinkHandle对象,并把创建好的socket传递给NetlinkHandle对象。

mHandler = new NetlinkHandler(mSock);
    if (mHandler->start()) {
        SLOGE("Unable to start NetlinkHandler: %s", strerror(errno));
        goto out;
    }

执行NetlinkHandle的start方法。


2.3:coldboot("/sys/block");方法

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);
        }
    }
}

此方法是往/sys/block文件夹下的设备文件中写入内容,从而触发kernel发送Uevent事件。


3、NetlinkHandler执行start方法

NetlinkHandler的start方法,最终会执行SocketListener中:

int NetlinkHandler::start() {
    return this->startListener();
}
SocketListener
int SocketListener::startListener() {
    return startListener(4);
}

int SocketListener::startListener(int backlog) {

    if (!mSocketName && mSock == -1) {
        SLOGE("Failed to start unbound listener");
        errno = EINVAL;
        return -1;
    } else if (mSocketName) {
        if ((mSock = android_get_control_socket(mSocketName)) < 0) {
            SLOGE("Obtaining file descriptor socket '%s' failed: %s",
                 mSocketName, strerror(errno));
            return -1;
        }
        SLOGV("got mSock = %d for %s", mSock, mSocketName);
    }

    if (mListen && listen(mSock, backlog) < 0) {
        SLOGE("Unable to listen on socket (%s)", strerror(errno));
        return -1;
    } else if (!mListen)
        mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));

    if (pipe(mCtrlPipe)) {
        SLOGE("pipe failed (%s)", strerror(errno));
        return -1;
    }

    if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
        SLOGE("pthread_create (%s)", strerror(errno));
        return -1;
    }

    return 0;
}
这里主要处理了3件事情:

1、以mSock作为参数,构建SocketClient,并加入到mClient中。

mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));

2、创建管道,进行读取和写入操作。

if (pipe(mCtrlPipe)) {
        SLOGE("pipe failed (%s)", strerror(errno));
        return -1;
    }

3、创建线程SocketListener,并执行。

if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
        SLOGE("pthread_create (%s)", strerror(errno));
        return -1;
    }
5、那么我们接下来的流程就到了NetlinkHandler创建的线程的执行中。
void *SocketListener::threadStart(void *obj) {
    SocketListener *me = reinterpret_cast<SocketListener *>(obj);

    me->runListener();
    pthread_exit(NULL);
    return NULL;
}

执行runListener方法:

这个方法会做如下事情 :

socket获取kernel上报的NetLinkEvent并回调onEvent方法。

NetlinkEvent *evt = new NetlinkEvent();
    if (evt->decode(mBuffer, count, mFormat)) {
        onEvent(evt);
    } else if (mFormat != NETLINK_FORMAT_BINARY) {
        // Don't complain if parseBinaryNetlinkMessage returns false. That can
        // just mean that the buffer contained no messages we're interested in.
        SLOGE("Error decoding NetlinkEvent");
    }
最终:NetLinkHandler方法执行onEvent方法:

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);
    }

其会调用VolumeManager的handleBlockEvent方法。





你可能感兴趣的:(vold,NetlinkHandler)