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



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android 12的ADB源代码是指Android开发者桥接(Android Debug Bridge,简称ADB)的源代码。ADB是一个多功能命令行工具,用于与Android设备进行通信和调试。在Android开发过程中,ADB源代码对于理解和调试设备与计算机之间的交互非常有用。 ADB源代码在Android开源项目(AOSP)的代码库中可用,并且可以通过下载AOSP来获取该源代码。通过查看源代码,我们可以了解ADB是如何实现与Android设备之间的通信和数据传输的。 ADB源代码包含了ADB客户端和ADB服务端的实现。ADB客户端在计算机上运行,而ADB服务端则在Android设备上运行。源代码中涵盖了各种命令和功能,包括连接设备、获取设备信息、安装和卸载应用程序、传输文件等。 了解ADB源代码可以帮助开发者理解ADB工具的工作原理和内部机制。这对于开发者在调试和优化应用程序时非常有帮助,可以更好地利用ADB的各种功能来帮助开发过程。 总而言之,Android 12的ADB源代码是开发者可以获取和查看的ADB工具的源代码,通过了解该源代码,开发者可以更好地了解ADB的工作原理和内部机制,并在开发中更好地应用ADB的各种功能。 ### 回答2: Android 12是谷歌推出的最新操作系统版本,它带来了许多新功能和改进。ADB(安卓调试桥)则是开发者工具包中的一个重要组件,它允许开发者在计算机和Android设备之间进行通信和调试。ADB的源代码在Android源代码中可以找到。 ADB源码位于Android源码的“platform/system/core/adb”目录下。这个目录包含ADB的所有关键组件。ADB源码以C/C++编写,开发者可以查看和修改这些代码以满足自己的需求。 在Android 12中,ADB源码可能会有一些变化和更新。这些变化可能包括新的功能、性能改进和bug修复。开发者可以通过查看和分析源码,了解这些变化并将其应用于自己的项目中。 为了使用ADB源码,开发者需要首先通过下载和编译整个Android源代码来获取它。一旦获取到ADB源码,开发者可以使用适当的编译工具将其编译为可执行文件。然后,通过在计算机上执行编译后的二进制文件,开发者就可以与连接的Android设备进行通信和调试。 总之,Android 12中ADB的源代码可以在Android源代码的特定目录中找到。开发者可以通过查看和修改这些源码来了解和应用ADB的最新功能和改进。同时,获取和编译Android源代码也是使用ADB源码的前提条件。 ### 回答3: Android 12的ADB源码指的是Android操作系统12版本中的ADBAndroid Debug Bridge)相关代码。 ADBAndroid开发平台中的一个调试工具,它能够通过USB电缆或Wi-Fi连接设备和计算机,实现设备和计算机之间的通信和数据传输。ADB源码包含了ADB守护进程(adbd)以及与其相关的各种组件和功能的实现代码。 在Android 12中,ADB源码经过了诸多改进和更新。其中包括对ADB连接的性能和稳定性的优化,以提高调试和数据传输的效率。此外,还增加了一些新的功能和命令,便于开发者进行更多的调试和测试工作。 ADB源码主要由C++语言编写,涉及到与底层系统中的设备驱动程序和底层服务的交互。开发者可以通过查看并分析ADB源码,深入了解ADB的工作原理和实现细节,以及针对特定需求进行二次开发和定制。 要查看Android 12中的ADB源码,需要访问Android开源项目(AOSP)的代码库。通过AOSP,开发者可以获取Android操作系统的全部源代码,包括ADB源码。但需要注意的是,访问和使用AOSP的源码需要先了解相关的法律政策和使用条款,并按照规定进行操作。 总之,Android 12的ADB源码是指Android 12版本中ADB相关的代码实现,通过查看和分析源码,开发者可以深入了解ADB的工作原理和实现细节,并进行二次开发和定制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值