浅析linux开发工具adb具体实现

    技术2025-10-23  11

    浅析linux开发工具adb具体实现

    浅析linux开发工具adb具体实现《再次浅析adb shell,pc daemon和手机daemon三者之间的数据交互流程《浅析adb创建流程》//===============================adb启动shell用到的命令export ADBHOST=192.168.100.2adb kill-serveradb start-server11:31:27adb shell //===============================让我们来分析一下对应的代码adb start-server==>main==>adb_commandline==>do_cmd==>adb_connect("host:start-server");如果是adb start-server命令==>fd = _adb_connect("host:version");    _adb_connect    fd = socket_loopback_client(ADB_PORT, SOCK_STREAM);//尝试连接127.0.0.1本机ip地址对应的ADB_PORT端口server    如果fd小于0,那么函数返回-2,否则在ADB_PORT端口打开server成功,    snprintf(tmp, sizeof tmp, "%04x", len);    if (writex(fd, tmp, 4) || writex(fd, service, len)) //先将4字节长度发送给server,然后发送命令数据"host:start-server"    adb_status(fd);    readx(fd, buf, 4);//读取server对该命令的反馈信息    if (!memcmp(buf, "OKAY", 4))//server成功处理    if (memcmp(buf, "FAIL", 4))//server返回了非FAIL值,那么说明server出现协议数据异常,直接退出==>如果没有启动server,那么fd将等于-2    if(fd == -2) {        fprintf(stdout,"* daemon not running. starting it now */n");    start_server:        if(launch_server(0)) {            fprintf(stderr,"* failed to start daemon */n");            return -1;        } else {            fprintf(stdout,"* daemon started successfully */n");        }        /* give the server some time to start properly and detect devices */        adb_sleep_ms(2000);        // fall through to _adb_connect    }==>launch_server==>    pipe(fd);    pid_t pid = fork();    if (pid == 0) {        //子线程[luther.gliethttp]        adb_close(fd[0]);        dup2(fd[1], STDERR_FILENO);//将pipe[1]的描述符dup2到stderr上,        //因为execl操作只会装入新的执行程序代码,然后取代调用execl的child子进程继续在用户空间执行,        //并不会改变内核空间的fd_tables[],所以execl运行的程序送往stderr上的数据就是送到parent的pipe[0]管道.        adb_close(fd[1]);        int result = execl(path, "adb", "fork-server", "server", NULL);     // this should not return        //永远不会返回到这里,因为位于用户空间的这里的代码,已经被execl操作替换成adb fork-server server程序了,        //这里的代码已经被覆盖,不存在了,所以当然不会返回到这里了[luther.gliethttp]     fprintf(stderr, "OOPS! execl returned %d, errno: %d/n", result, errno);    } else {        char temp[3];        temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';        // wait for the "OK/n" message        adb_close(fd[1]);        int ret = adb_read(fd[0], temp, 3);//等待管道数据的到来        /*        static __inline__ int adb_read(int fd, void* buf, size_t len)        {            return read(fd, buf, len);        }        */        adb_close(fd[0]);        if (ret < 0) {            fprintf(stderr, "could not read ok from ADB Server, errno = %d/n", errno);            return -1;        }        if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '/n') {            fprintf(stderr, "ADB server didn't ACK/n" );            return -1;        }        // run a program in a new session        setsid();//之前parent和child运行在同一个session里,而且parent是session头,所以,        //所以作为session头的parent如果exit结束执行的话,那么会话session组中的所有进程将都被杀死,        //所以执行setsid()之后,parent将重新获得一个新的会话session组id,child将仍持有原有的会话session组,        //这时parent退出之后,将不会影响到child了[luther.gliethttp].    }来看看fork之后execl执行的过程[luther.gliethttp]adb fork-server server==>main==>adb_commandline    if (!strcmp(argv[0], "fork-server")) {        /* this is a special flag used only when the ADB client launches the ADB Server */        is_daemon = 1;    }        if ((argc > 0) && (!strcmp(argv[0],"server"))) {        if (no_daemon || is_daemon) {            r = adb_main(is_daemon);//完成daemon启动        } else {            r = launch_server();        }        if(r) {            fprintf(stderr,"* could not start server */n");        }        return r;    }==>adb_main    init_transport_registration    HOST = 1;    usb_init();    local_init();    if(install_listener("tcp:5037", "*smartsocket*", NULL)) {        exit(1);    }    if (is_daemon) {        fprintf(stderr, "OK/n");//将OK传递给上面parent执行adb_read(fd[0], temp, 3);管道接收函数.        start_logging();//打开log文件,然后dup2到stdout和stderr,    }    fdevent_loop();    usb_cleanup();//================================void start_logging(void){    int fd;    fd = unix_open("/dev/null", O_RDONLY);    dup2(fd, 0);//取消输入通道stdin    fd = unix_open("/tmp/adb.log", O_WRONLY | O_CREAT | O_APPEND, 0640);//创建/tmp/adb.log文件    if(fd < 0) {        fd = unix_open("/dev/null", O_WRONLY);//如果不成功,那么执行/dev/null    }    dup2(fd, 1);//将文件句柄dup2到stdout    dup2(fd, 2);//将文件句柄dup2到stderr    fprintf(stderr,"--- adb starting (pid %d) ---/n", getpid());//向/tmp/adb.log文件写入log数据[luther.gliethttp]}//================================void fdevent_loop(){    fdevent *fde;        for(;;) {        fdevent_process();                while((fde = fdevent_plist_dequeue())) {            unsigned events = fde->events;            fde->events = 0;            fde->state &= (~FDE_PENDING);            dump_fde(fde, "callback");            fde->func(fde->fd, events, fde->arg);        }    }}//==================================>install_listener    fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);==>fdevent_install     fde->func = func;    fdevent_connect(fde);==>ss_listener_event_func==>connect_to_smartsocket    asocket *ss = create_smart_socket(smart_socket_action);==>create_smart_socket    s->enqueue = smart_socket_enqueue;==>smart_socket_enqueue==>handle_host_request==>local_connect    ...    fd = socket_loopback_client(port, SOCK_STREAM);#if ADB_HOST    if(fd < 0) {        const char *host = getenv("ADBHOST");        if(host) {            fd = socket_network_client(host, port, SOCK_STREAM);        }    }#endif//================================init_transport_registrationvoid init_transport_registration(void){    int s[2];    if(adb_socketpair(s)){//创建一对unix通信socket        fatal_errno("cannot open transport registration socketpair");    }    transport_registration_send = s[0];//用来发送    transport_registration_recv = s[1];//用来接收    fdevent_install(&transport_registration_fde,                    transport_registration_recv,//注册接收socket作为epoll等待信息来源                    transport_registration_func,//对接收到的数据执行处理操作的func                    0);    fdevent_set(&transport_registration_fde, FDE_READ);//登记为READ类型}fdevent_install==>fdevent_register==>fd_table[fde->fd] = fde;//这里fd_table是模拟kernel实现方式,因为fde->fd由内核获取,所以可以保证其值的唯一性.==>fde->state |= FDE_ACTIVE;//置state为激活fdevent_set(&transport_registration_fde, FDE_READ);==>void fdevent_set(fdevent *fde, unsigned events){    ...    if(fde->state & FDE_ACTIVE) {        fdevent_update(fde, events);//刷新该fde->fd到epoll中        dump_fde(fde, "update");    }    fde->state = (fde->state & FDE_STATEMASK) | events;//保存信息    ...}static void fdevent_update(fdevent *fde, unsigned events){    struct epoll_event ev;    int active;        active = (fde->state & FDE_EVENTMASK) != 0;        memset(&ev, 0, sizeof(ev));    ev.events = 0;//清0    ev.data.ptr = fde;//置数据指针    if(events & FDE_READ) ev.events |= EPOLLIN;//置in事件    if(events & FDE_WRITE) ev.events |= EPOLLOUT;//置out事件    if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);    fde->state = (fde->state & FDE_STATEMASK) | events;    if(active) {        ...    } else {            /* we're not active. if we're watching events, we need            ** to add, otherwise we can just do nothing            */        if(ev.events) {            if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {//添加到epoll_fd中                perror("epoll_ctl() failed/n");                exit(1);            }        }    }}static int epoll_fd = -1;static void fdevent_init(){    /* XXX: what's a good size for the passed in hint? */    epoll_fd = epoll_create(256);        if(epoll_fd < 0) {        perror("epoll_create() failed");        exit(1);    }    /* mark for close-on-exec */    fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);}static void fdevent_process(){    struct epoll_event events[256];    fdevent *fde;    int i, n;    n = epoll_wait(epoll_fd, events, 256, -1);//等待添加到epoll_fd中的各个fd对应event事件发生[luther.gliethttp]    ...    for(i = 0; i < n; i++) {        struct epoll_event *ev = events + i;        fde = ev->data.ptr;        if(ev->events & EPOLLIN) {            fde->events |= FDE_READ;        }        if(ev->events & EPOLLOUT) {            fde->events |= FDE_WRITE;        }        if(ev->events & (EPOLLERR | EPOLLHUP)) {            fde->events |= FDE_ERROR;        }        if(fde->events) {            if(fde->state & FDE_PENDING) continue;//正在处理前一条信息            fde->state |= FDE_PENDING;            fdevent_plist_enqueue(fde);//放入待处理的list链表上        }    }}static void fdevent_plist_enqueue(fdevent *node){    fdevent *list = &list_pending;//需要处理所有pending任务的链表    node->next = list;    node->prev = list->prev;    node->prev->next = node;    list->prev = node;}static fdevent *fdevent_plist_dequeue(void)//从pending任务链表摘下一个node来处理{    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;}void fdevent_loop(){    fdevent *fde;        for(;;) {        fdevent_process();        while((fde = fdevent_plist_dequeue())) {            unsigned events = fde->events;            fde->events = 0;//复位成0            fde->state &= (~FDE_PENDING);//事件检查和前期处理完成,之后将执行事件对应的func,所以清除pending标志,允许该sock接受下一个event的添加[luther.gliethttp]            dump_fde(fde, "callback");            fde->func(fde->fd, events, fde->arg);        }    }}adb_main==>init_transport_registration==>usb_init    adb_thread_create(&tid, device_poll_thread, NULL)//创建thread==>local_init    adb_thread_create(&thr, client_socket_thread, 0)//host对应的处理函数,对于client,对应server_socket_threadtransport_registration_send === transport_registration_recv [FDE_READ]=== transport_registration_func"tcp:5037" === local_name_to_fd("tcp:5037") [FDE_READ]=== ss_listener_event_func //处理来自loopback端口5037的sock数据                                    === 尝试连接到"tcp:5037"上的client们 === local_socket_event_func并将"tcp:5037"这个sock添加到listener_list链表上好了,我们的server已经成功起来了,来看一个命令交互:adb shell1.本地执行adb shelladb shell==>main==>adb_commandline==>interactive_shell==>fd = adb_connect("shell:");    int fd = _adb_connect("host:version");//因为server在上面已经打开,所以将成功链接    fd = socket_loopback_client(ADB_PORT, SOCK_STREAM);//打开127.0.0.1本地机tcp:5037端口    //对于server端,fdevent_process()==>epoll_wait(epoll_fd, events, 256, -1);将返回,触发server启动时install_listener("tcp:5037", "*smartsocket*", NULL);注册登记的    //回调函数ss_listener_event_func在fdevent_loop中被执行.    if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd))//非host命令,//发送"host:transport-any"命令给server    adb_status(fd);//读取"host:version"命令的返回,对于host就是调用    //handle_host_request()==>    //#define ADB_SERVER_VERSION 20    //if (!strcmp(service, "version")) {    // char version[12];    // snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);    // snprintf(buf, sizeof buf, "OKAY%04x%s", (unsigned)strlen(version), version);    // writex(reply_fd, buf, strlen(buf));    // return 0;    //}    //在OKAY00040014switch_socket_transport对于server端来说对应==>==>handle_host_request    if (!strncmp(service, "transport", strlen("transport"))) {        ...    } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {            type = kTransportAny;    }    ...    transport = acquire_one_transport(CS_ANY, type, serial, &error_string);//就是从transport_list链表上摘下一个登记了的transport,对于我们分析的adb shell就是//init_transport_registration==>transport_registration_func==>会追加transport_list链表//fdevent_install(&transport_registration_fde,// transport_registration_recv,// transport_registration_func,// 0);    if (transport) {        s->transport = transport;        adb_write(reply_fd, "OKAY", 4);    }int adb_status(int fd){    unsigned char buf[5];    unsigned len;    if(readx(fd, buf, 4)) {        strcpy(__adb_error, "protocol fault (no status)");        return -1;    }    if(!memcmp(buf, "OKAY", 4)) {        return 0;//ok,server正常返回数据,退出,进一步处理    }    if(memcmp(buf, "FAIL", 4)) {        sprintf(__adb_error,                "protocol fault (status %02x %02x %02x %02x?!)",                buf[0], buf[1], buf[2], buf[3]);        return -1;    }    if(readx(fd, buf, 4)) {//错误:读取返回数据长度        strcpy(__adb_error, "protocol fault (status len)");        return -1;    }    buf[4] = 0;    len = strtoul((char*)buf, 0, 16);//错误:转换长度数据    if(len > 255) len = 255;    if(readx(fd, __adb_error, len)) {//错误:读取数据        strcpy(__adb_error, "protocol fault (status read)");        return -1;    }    __adb_error[len] = 0;    return -1;}
    最新回复(0)