android adb源码分析(3)

本篇分析fdevent.c的源代码。

这个源代码文件的工作时创建、监听和处理读写事件。

static fdevent **fd_table = 0;
static int fd_table_max = 0;

fd_table保存的是以fdevent->fd为索引保存的fdevent指针,即

the_fdevent的值等于fd_table[the_fdevent->fd]。

static void fdevent_register(fdevent *fde)  //即将fde添加到fd_table
{
    if(fde->fd < 0) {
        FATAL("bogus negative fd (%d)\n", fde->fd);
    }

    if(fde->fd >= fd_table_max) {  //这段代码即初始化或自动增长fd_table
        int oldmax = fd_table_max;
        if(fde->fd > 32000) {
            FATAL("bogus huuuuge fd (%d)\n", fde->fd);
        }
        if(fd_table_max == 0) {
            fdevent_init();
            fd_table_max = 256;
        }
        while(fd_table_max <= fde->fd) {
            fd_table_max *= 2;
        }
        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
        if(fd_table == 0) {
            FATAL("could not expand fd_table to %d entries\n", fd_table_max);
        }
        memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
    }

    fd_table[fde->fd] = fde;   //将fde添加到fd_table
}

static void fdevent_unregister(fdevent *fde) //这个函数即将fde从fd_table中删除
{
    if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
        FATAL("fd out of range (%d)\n", fde->fd);
    }

    if(fd_table[fde->fd] != fde) {
        FATAL("fd_table out of sync [%d]\n", fde->fd);
    }

    fd_table[fde->fd] = 0;

    if(!(fde->state & FDE_DONT_CLOSE)) { //如果fde->fd打开了并没有关闭,需要执行关闭操作
        dump_fde(fde, "close");
        adb_close(fde->fd);
    }
}

fdevent是代码处理事件的载体,它的定义如下:

struct fdevent 
{
    fdevent *next;     //循环链表
    fdevent *prev;

    int fd;         //句柄
    int force_eof;

    unsigned short state;     //低8位表示事件,高8位表示状态
    unsigned short events;    //需要处理的事件

    fd_func func;         //事件处理回调函数
    void *arg;            //参数
};

其中事件可以是:

#define FDE_READ              0x0001
#define FDE_WRITE             0x0002
#define FDE_ERROR             0x0004
#define FDE_TIMEOUT           0x0008
#define FDE_DONT_CLOSE       0x0080

//掩码
#define FDE_EVENTMASK  0x00ff

状态可以是:

#define FDE_ACTIVE     0x0100
#define FDE_PENDING    0x0200
#define FDE_CREATED    0x0400

//掩码
#define FDE_STATEMASK  0xff00

注意,这些状态是可以同时存在的。

当调用fdevent_create()后,FDE_CREATED标志被设置,当调用fdevent_install()后, FDE_CREATED标志被设置,但在fdevent_create()内部调用了fdevent_install(),所以调用fdevent_create()都被设置了。当有事件在调用select发生后,相应的事件state会设置为FDE_PENDING,当事件处理完后这个标志又被删除。相应的代码是:

void fdevent_loop()
{
    fdevent *fde;
    fdevent_subproc_setup();

    for(;;) {
        D("--- ---- waiting for events\n");

        fdevent_process(); //在这个函数中调用select,当有事件发生时,state被设置为FDE_PENDING,event也会被设置。所有的pending事件都会被保存在全局变量list_pending中。

        while((fde = fdevent_plist_dequeue())) {   //处理list_pending变量的事件
            fdevent_call_fdfunc(fde);
        }
    }
}

list_pending的相关代码:

//变量定义和初始化
static fdevent list_pending = {
    .next = &list_pending,
    .prev = &list_pending,
};

//添加一个元素
static void fdevent_plist_enqueue(fdevent *node)
{
    fdevent *list = &list_pending;

    node->next = list;
    node->prev = list->prev;
    node->prev->next = node;
    list->prev = node;
}

//删除一个指定元素
static void fdevent_plist_remove(fdevent *node)
{
    node->prev->next = node->next;
    node->next->prev = node->prev;
    node->next = 0;
    node->prev = 0;
}

//从list中取出一个元素
static fdevent *fdevent_plist_dequeue(void)
{
    fdevent *list = &list_pending;
    fdevent *node = list->next;

    if(node == list) return 0;

    list->next = node->next;
    list->next->prev = list;
    node->next = 0;
    node->prev = 0;

    return node;
}

事件的处理是阻塞方式的,可以有两种代码实现方法。定义宏CRAPTASTIC表示使用epoll的方式,否则使用select方式。我这里只讲select的处理方式:

static fd_set read_fds;        //读事件集合
static fd_set write_fds;       //写事件集合
static fd_set error_fds;       //发生错误事件集合

static int select_n = 0;

static void fdevent_init(void)  //初始化
{
    FD_ZERO(&read_fds);
    FD_ZERO(&write_fds);
    FD_ZERO(&error_fds);
}

static void fdevent_connect(fdevent *fde)   //添加
{
    if(fde->fd >= select_n) {
        select_n = fde->fd + 1;
    }
}

static void fdevent_disconnect(fdevent *fde)  //从所有事件集合删除fde
{
    int i, n;

    FD_CLR(fde->fd, &read_fds);
    FD_CLR(fde->fd, &write_fds);
    FD_CLR(fde->fd, &error_fds);

    for(n = 0, i = 0; i < select_n; i++) {
        if(fd_table[i] != 0) n = i;
    }
    select_n = n + 1;
}

static void fdevent_update(fdevent *fde, unsigned events)//根据events设置事件集合
{
    if(events & FDE_READ) {
        FD_SET(fde->fd, &read_fds);
    } else {
        FD_CLR(fde->fd, &read_fds);
    }
    if(events & FDE_WRITE) {
        FD_SET(fde->fd, &write_fds);
    } else {
        FD_CLR(fde->fd, &write_fds);
    }
    if(events & FDE_ERROR) {
        FD_SET(fde->fd, &error_fds);
    } else {
        FD_CLR(fde->fd, &error_fds);
    }

    fde->state = (fde->state & FDE_STATEMASK) | events;
}

/* Looks at fd_table[] for bad FDs and sets bit in fds.
** Returns the number of bad FDs.
*/
static int fdevent_fd_check(fd_set *fds) //通过调用fcntl来判断是否是一个有效的fdevent
{
    int i, n = 0;
    fdevent *fde;

    for(i = 0; i < select_n; i++) {
        fde = fd_table[i];
        if(fde == 0) continue;
        if(fcntl(i, F_GETFL, NULL) < 0) {
            FD_SET(i, fds);
            n++;
            // fde->state |= FDE_DONT_CLOSE;

        }
    }
    return n;
}

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/xgbing/article/details/52065277
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞