ADB 分析

ADB 分析



让我们来分析一下对应的代码
adbstart-server
==>main
==>adb_commandline
==>do_cmd
==>adb_connect("host:start-server");
如果是adbstart-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 serversome 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]的描述符dup2stderr,

       //因为execl操作只会装入新的执行程序代码,然后取代调用execlchild子进程继续在用户空间执行,

       //并不会改变内核空间的fd_tables[],所以execl运行的程序送往stderr上的数据就是送到parentpipe[0]管道.

       adb_close(fd[1]);
       int result = execl(path, "adb", "fork-server","server", NULL);
     // this shouldnot return

       //永远不会返回到这里,因为位于用户空间的这里的代码,已经被execl操作替换成adbfork-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();//之前parentchild运行在同一个session,而且parentsession,所以,

       //所以作为session头的parent如果exit结束执行的话,那么会话session组中的所有进程将都被杀死,

       //所以执行setsid()之后,parent将重新获得一个新的会话sessionid,child将仍持有原有的会话session,

       //这时parent退出之后,将不会影响到child[luther.gliethttp].

    }
来看看fork之后execl执行的过程[luther.gliethttp]
adbfork-server server
==>main
==>adb_commandline
   if (!strcmp(argv[0], "fork-server")) {
       /* this is a special flag used only when the ADB client launches theADB 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文件,然后dup2stdoutstderr,

    }
   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);//
将文件句柄dup2stdout

    dup2(fd, 2);//将文件句柄dup2stderr

    fprintf(stderr,"--- adbstarting (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_registration
voidinit_transport_registration(void)
{
    ints[2];

    if(adb_socketpair(s)){//创建一对unix通信socket

        fatal_errno("cannotopen 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, unsignedevents)
{
    ...
   if(fde->state & FDE_ACTIVE) {
       fdevent_update(fde, events);//
刷新该fde->fdepoll

        dump_fde(fde,"update");
    }
   fde->state = (fde->state & FDE_STATEMASK) | events;//
保存信息

    ...
}

static void fdevent_update(fdevent *fde, unsignedevents)
{
    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_thread

 


transport_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端口5037sock数据

                                   === 尝试连接到"tcp:5037"上的client===local_socket_event_func
并将"tcp:5037"这个sock添加到listener_list链表上


好了,我们的server已经成功起来了,来看一个命令交互:adbshell
1.
本地执行adbshell
adbshell
==>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_funcfdevent_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, sizeofversion, "%04x", ADB_SERVER_VERSION);

    // snprintf(buf, sizeof buf,"OKAY%04x%s", (unsigned)strlen(version), version);

    // writex(reply_fd, buf,strlen(buf));

    // return 0;

    //}

    //OKAY00040014


switch_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,对于我们分析的adbshell就是

//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)) {
        return0;//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;
}

==>int adb_connect(const char *service)
==>intfd = _adb_connect("host:version");
==>
   else {
    // if server was running, check itsversion to make sure it is not out of date

        charbuf[100];
        intn;
        int version =ADB_SERVER_VERSION - 1;//
先置个非法值


        // ifwe have a file descriptor, then parse version result

        if(fd >=0) {
     if(readx(fd, buf, 4)) gotoerror;//
读取数据长度


         buf[4]= 0;
         n =strtoul(buf, 0, 16);//
转换长度数据

         if(n> (int)sizeof(buf)) goto error;
        if(readx(fd, buf, n)) goto error;//
读取server返回的数据

        adb_close(fd);//关闭fd


           if (sscanf(buf, "%04x", &version) != 1)goto error;//server返回的version数据转储到version变量中

        } else{
           // if fd is -1, then check for "unknown host service",

           // which would indicate a version of adb that does notsupport the version command

           if (strcmp(__adb_error, "unknown host service")!= 0)
               return fd;
        }

        if(version!= ADB_SERVER_VERSION) {//版本不匹配

     printf("adb server isout of date. killing.../n");
     fd =_adb_connect("host:kill");
    adb_close(fd);

               /* XXX can we better detect its death? */
    adb_sleep_ms(2000);
           goto start_server;
     }
   }

    // if the command is start-server,we are done.

    if (!strcmp(service,"host:start-server"))
       return 0;
//
好了,说明server正常返回了_adb_connect("host:version");命令,所以我们可以放心的传送adb_connect命令需要传送的service命令了,并为该service命令创建一个与server服务器连接句柄fd.,这里就是我们上面的fd= adb_connect("shell:");它不是host命令.

    fd = _adb_connect(service);
   if(fd == -2) {
       fprintf(stderr,"** daemon still not running");
   }

    return fd;
   
2.
server
==>fdevent_process
==>fde= fdevent_plist_dequeue()
==> fde->func(fde->fd, events,fde->arg)
==>ss_listener_event_func//"tcp:5037"
端口数据处理回调函数

==>fd = adb_socket_accept(_fd, &addr,&alen);//接受clientsocket_loopback_client(ADB_PORT,SOCK_STREAM);连接,并为该新连接建立fd处理句柄

==>s =create_local_socket(fd);//登记新建立的套接字到fd_table[fde->fd]= fde;,回调函数为local_socket_event_func

==>connect_to_smartsocket(s);//为该socket链接创建peer处理函数,然后调用ready==>local_socket_ready==>fdevent_add(&amp;s->fde, FDE_READ);将本fde添加到epoll[如果不明确调用epoll_ctl(epoll_fd,EPOLL_CTL_DEL, fde->fd,&ev);执行删除操作,那么它将永远在epoll]等待该client发送数据过来,然后执行s->peer->enqueue(s->peer,p);数据函数,:smart_socket_enqueue.


static void ss_listener_event_func(int _fd,unsigned ev, void *_l)
{
    asocket *s;

    if(ev & FDE_READ) {
       struct sockaddr addr;
       socklen_t alen;
        int fd;

        alen =sizeof(addr);
        fd =adb_socket_accept(_fd, &addr,&alen);//
接受clientsocket_loopback_client(ADB_PORT,SOCK_STREAM);连接,并为该新连接建立fd处理句柄

        if(fd <0) return;

       adb_socket_setbufsize(fd, CHUNK_SIZE);//设置新建立的套接字缓冲大小


        s =create_local_socket(fd);//登记新建立的套接字到fd_table[fde->fd]= fde;,回调函数为local_socket_event_func

        if(s){
           connect_to_smartsocket(s);
//
创建peer处理函数,然后调用ready==>local_socket_ready==>fdevent_add(&s->fde,FDE_READ);将本fde添加到epoll,等待该client数据的到来,

//当接收完数据之后,调用s->peer->enqueue(s->peer,p);函数,:smart_socket_enqueue,对数据进一步深入处理

           return;
        }

        adb_close(fd);
   }
}

asocket *create_local_socket(int fd)
{
   asocket *s = calloc(1, sizeof(asocket));
    if(s== 0) fatal("cannot allocate socket");
   install_local_socket(s);
    s->fd = fd;
   s->enqueue = local_socket_enqueue;
    s->ready= local_socket_ready;//fdevent_add(&s->fde,FDE_READ);
将本fde添加到epoll

    s->close = local_socket_close;

    fdevent_install(&s->fde,fd, local_socket_event_func, s);
/* fdevent_add(&s->fde,FDE_ERROR); */
    //fprintf(stderr, "Createdlocal socket in create_local_socket /n");

    D("LS(%d): created(fd=%d)/n", s->id, s->fd);
    returns;
}

void connect_to_smartsocket(asocket *s)
{
   D("Connecting to smart socket /n");
   asocket *ss = create_smart_socket(smart_socket_action);
   s->peer = ss;//
创建对等的peer对象,这样彼此将互相转送数据[luther.gliethttp]

    ss->peer = s;
   s->ready(s);//
调用ready==>local_socket_ready==>fdevent_add(&s->fde,FDE_READ);将本fde添加到epoll.

}

asocket *create_smart_socket(void(*action_cb)(asocket *s, const char *act))
{
   D("Creating smart socket /n");
   asocket *s = calloc(1, sizeof(asocket));
    if(s== 0) fatal("cannot allocate socket");
   s->id = 0;
    s->enqueue =smart_socket_enqueue;//
数据处理函数

    s->ready =smart_socket_ready;
    s->close =smart_socket_close;
    s->extra = action_cb;

    D("SS(%d): created %p/n",s->id, action_cb);
    returns;
}
3.
建立的连接socket处理流程
fdevent_loop
==>local_socket_event_func//
实现通过connect连接到127.0.0.1本地机tcp:5037端口上的一个client数据收发处理

    if (ev & FDE_READ) {
       ...
        adb_read(fd, x,avail);//
读取client发送过来的数据

        ...
       s->peer->enqueue(s->peer,p);//
将接收到的client数据递交给peer,smart_socket_enqueue()函数完成数据处理[luther.gliethttp]

        ...
   }

==>smart_socket_enqueue
    len= unhex(p->data, 4);//
解出长度

    service = (char *)p->data +4;//读取服务命令字


   //处理所有service服务命令,比如:_adb_connect("host:version");

    handle_host_request(service,ttype, serial, s->peer->fd, s)
   //
返回给s->peer->fd

    //这里s->peer就是上面s= create_local_socket(fd);创建的asocket,

    //s->peer->fd就是上面fd= adb_socket_accept(_fd, &addr, &alen);client打开的socket连接,所以

   //s->peer->fd的数据发送将,通过本地机tcp:5037端口socket发送到client.

    create_host_service_socket//如果是一个驻留服务

    ...
   //
对于我们的adbshell命令将执行到下面

    s->peer->ready =local_socket_ready_notify;
    s->peer->close= local_socket_close_notify;
    s->peer->peer= 0;
        /* give him ourtransport and upref it */
    s->peer->transport= s->transport;

    //对于我们的adbshell命令就是connect_to_remote(s->peer,"shell:");

    connect_to_remote(s->peer,(char*) (p->data + 4));
    s->peer = 0;
   s->close(s);
    return 1;

void connect_to_remote(asocket *s, const char*destination)
{
    D("Connect_to_remotecall /n");
    apacket *p = get_apacket();
   int len = strlen(destination) + 1;

    if(len > (MAX_PAYLOAD-1)){
        fatal("destinationoversized");
    }

    D("LS(%d): connect('%s')/n",s->id, destination);
    p->msg.command =A_OPEN;
    p->msg.arg0 = s->id;
   p->msg.data_length = len;
    strcpy((char*)p->data, destination);//destination
"shell:"

    send_packet(p,s->transport);//发送remote连接命令

}


==>init_transport_registration
==>transport_registration_send= s[0];
   transport_registration_recv =s[1];//
等待transport_registration_send管道数据

==>fdevent_install(&transport_registration_fde,
                   transport_registration_recv,
                   transport_registration_func,
                   0);
==>transport_registration_func
==>fdevent_install(&(t->transport_fde),
                   t->transport_socket,
                   transport_socket_events,
                   t);

==>register_socket_transport
==>init_socket_transport


luther@gliethttp:~$adb devices
* daemon not running. starting it now *
*daemon started successfully *
List of devices attached
emulator-5554    device


对于host启动
adb_main
==>local_init
==>adb_thread_create(&thr,client_socket_thread, 0)//
建立client_socket_thread线程

==>client_socket_thread
static void*client_socket_thread(void *x)
{
#if ADB_HOST
   #define ADB_LOCAL_TRANSPORT_PORT 5555
    int port= ADB_LOCAL_TRANSPORT_PORT;
    int count =ADB_LOCAL_TRANSPORT_MAX;

    D("transport:client_socket_thread() starting/n");

    /* try to connect to any number ofrunning emulator instances */
    /* this is onlydone when ADB starts up. later, each new emulator */
   /* will send a message to ADB to indicate that is is starting up*/
    for ( ; count > 0; count--, port += 2 ){
        (void)local_connect(port);//
扫描网络端口,尝试连接与本机pc连接的所有物理设备或者emulator设备

// Emulator 1, console: 5554

// Emulator 1, adb: 5555

// Emulator 2, console: 5556

// Emulator 2, adb: 5557 ...

    }
#endif
   return 0;//
线程执行完毕,安全退出.

}
#define LOCAL_CLIENT_PREFIX"emulator-"
==>local_connect
int local_connect(intport)
{
    char buf[64];
   int fd = -1;

    fd = socket_loopback_client(port,SOCK_STREAM);
#if ADB_HOST
    if(fd < 0){
        const char *host =getenv("ADBHOST");//
就是上面exportADBHOST=192.168.100.2设备地址

        if(host){
           fd = socket_network_client(host, port,SOCK_STREAM);//
连接192.168.100.2上的port端口,

//对于client端见后面分析

        }
   }
#endif
    if (fd >= 0) {
       D("client: connected on remote on fd %d/n", fd);
       close_on_exec(fd);
       disable_tcp_nagle(fd);
       snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, port- 1);
       register_socket_transport(fd, buf,port);//
登记到transport_list链表,作为数据传输通道之一[luther.gliethttp]

        return0;
    }
    return -1;
}

对于手机上client启动
adb_main
==>local_init
==>adb_thread_create(&thr,server_socket_thread, 0)//
建立server_socket_thread线程

==>server_socket_thread
   if(serverfd == -1) {
           serverfd = socket_inaddr_any_server(ADB_LOCAL_TRANSPORT_PORT,SOCK_STREAM);//
等待ADB_LOCAL_TRANSPORT_PORT端口数据到来

           if(serverfd < 0) {
               D("server: cannot bind socket yet/n");
               adb_sleep_ms(1000);
               continue;
           }
           close_on_exec(serverfd);
    }
   fd = adb_socket_accept(serverfd, &addr, &alen);//
接收到一个数据请求,

//由上面的

//==>local_connect

//==>socket_network_client(host, port,SOCK_STREAM);//连接192.168.100.2上的port端口

//发起该连接,进而执行register_socket_transportclient管理的transport_list链表登记注册

   register_socket_transport(fd,"host",ADB_LOCAL_TRANSPORT_PORT);//创建请求线程


==>register_socket_transport
==>register_transport
staticvoid register_transport(atransport *transport)
{
   tmsg m;
    m.transport = transport;
   m.action = 1;
    D("transport: %pregistered/n", transport);
   if(transport_write_action(transport_registration_send, &m)){
        fatal_errno("cannotwrite transport registration socket/n");
   }
}
这样与transport_registration_send配对的transport_registration_recv将接收到该数据,并且调用已经注册好的transport_registration_func()函数来进一步处理发送过去的数据,
==>transport_registration_func
==>transport_socket_events
==>voidhandle_packet(apacket *p, atransport *t)
    switch(p->msg.command) {
       case A_OPEN: /* OPEN(local-id, 0, "destination") */
       if(t->connection_state != CS_OFFLINE) {
           char *name = (char*) p->data;//
对于我们这里的分析就是"shell:"

           name[p->msg.data_length > 0 ? p->msg.data_length- 1 : 0] = 0;
           s = create_local_service_socket(name);//
根据name创建service

           if(s == 0) {
               send_close(0, p->msg.arg0, t);
           } else {
               s->peer = create_remote_socket(p->msg.arg0, t);
               s->peer->peer = s;
               send_ready(s->id, s->peer->id, t);
               s->ready(s);
           }
        }
       break;
==>asocket *create_local_service_socket(const char*name)
    fd = service_to_fd(name);//
就是ptm= unix_open("/dev/ptmx", O_RDWR);返回的主pty

    s =create_local_socket(fd);//这样sh通过ptspty发出的数据都将通过ptmpty发送到peer对应的fd,pc连接到手机端的socket,然后通过网络转发到pc,相应的,pc端下发过来的数据将通过建立的socket读取到,然后交由该socket对应的peer,:ptmxpty,进而将直接被传递到pty从设备,也就是下面将要看到的/system/bin/sh程序[luther.gliethttp].

    return s;

int service_to_fd(const char *name)
==>
   else if(!HOST && !strncmp(name, "shell:", 6)){//
对于我们这里的分析就是"shell:"

#if ADB_HOST
#define SHELL_COMMAND"/bin/sh"
#else
#define SHELL_COMMAND"/system/bin/sh"//
手机上的sh位置

#endif
       if(name[6]) {
           ret = create_subprocess(SHELL_COMMAND, "-c", name +6);
        } else{
           ret = create_subprocess(SHELL_COMMAND, "-", 0);
       }
        //ret = ptm
pty句柄

#if !ADB_HOST
    } elseif(!strncmp(name, "sync:", 5)) {
       ret = create_service_thread(file_sync_service, NULL);
   } else if(!strncmp(name, "remount:", 8)) {
       ret = create_service_thread(remount_service, NULL);
#endif
#if0
    } else if(!strncmp(name, "echo:",5)){
        ret =create_service_thread(echo_service, 0);
#endif
   }
//
让我们看看create_subprocess创建sh的函数体

//使用pty虚拟终端对,来完成创建工作

static int create_subprocess(const char *cmd, constchar *arg0, const char *arg1)
{
#ifdef HAVE_WIN32_PROC
   fprintf(stderr, "error: create_subprocess not implemented onWin32 (%s %s %s)/n", cmd, arg0, arg1);
   return -1;
#else /* !HAVE_WIN32_PROC */
    char*devname;
    int ptm;
    pid_tpid;
//
这里cmd就是"/system/bin/sh"//手机上的sh位置

    ptm = unix_open("/dev/ptmx",O_RDWR); // | O_NOCTTY);

    if(ptm < 0){
       printf("[ cannot open /dev/ptmx - %s]/n",strerror(errno));
       return -1;
    }
    fcntl(ptm,F_SETFD, FD_CLOEXEC);

    if(grantpt(ptm) || unlockpt(ptm)||
       ((devname = (char*)ptsname(ptm)) == 0)){//
获取从pty的设备名

        printf("[trouble with /dev/ptmx - %s ]/n", strerror(errno));
       return -1;
    }

    pid = fork();
   if(pid < 0) {
       printf("- fork failed: %s -/n", strerror(errno));
       return -1;
    }

    if(pid == 0){
       int pts;
//
子进程建立自己的新sessionid来和父进程完全独立开[luther.gliethttp]

        setsid();

        pts =unix_open(devname, O_RDWR);//打开pty从设备

        if(pts <0) exit(-1);

        dup2(pts,0);//stdin

        dup2(pts,1);//stdout

        dup2(pts,2);//stderr 都将被重定向到pts


        adb_close(ptm);

        execl(cmd,cmd, arg0, arg1, NULL);//执行/system/bin/sh

        fprintf(stderr,"- exec '%s' failed: %s (%d) -/n",
               cmd, strerror(errno), errno);
       exit(-1);
    } else {
       return ptm;
    }
#endif /* !HAVE_WIN32_PROC*/
}

手机上的clientadb执行server_socket_thread线程等待ADB_LOCAL_TRANSPORT_PORT端口发生连接请求,
pc
机端执行
exportADBHOST=192.168.100.2
adb kill-server //
杀死pc上的adbserver

adb start-server //重新启动adbserver,打开时,client_socket_thread==>local_connect连接192.168.100.2ADB_LOCAL_TRANSPORT_PORT端口,这样手机端的server_socket_thread线程将接收到ADB_LOCAL_TRANSPORT_PORT端口上的socket数据,然后登记该porttransport端口到transport_list链表上[luther.gliethttp]

adb shell //登录adbshell,打开/system/bin/sh在从pty,sh0,1,2句柄都将dup2ptspty对应的子进程上,然后ptmpty,将作为ADB_LOCAL_TRANSPORT_PORT端口上收发到数据后的转发peer对应的fd目的句柄,所以这样pc端的数据将通过socket发送到手机上的socket,手机上的socket处理函数local_socket_event_func==>local_socket_enqueue将从网络接收到的数据转发给peer,:ptmpty,进而被ptspty接收,也就是传递给了将0,1,2句柄dup2ptspty上的/system/bin/sh应用程序,/system/bin/sh输出的结果通过ptspty传递给ptmpty,然后ptmpty,发送到peer对应的fd,pc连接到手机端的socket,然后通过网络转发到pc,adb的大体流程就是这个样子,当然还有很多细节,以后有时间再慢慢研究了


adb shell程序执行流程:

system/core/adb/adb.c

int adb_main(int is_daemon, intserver_port)

{

#if !ADB_HOST

int port;

char value[PROPERTY_VALUE_MAX];

umask(000);

#endif

atexit(adb_cleanup);

#ifdef HAVE_WIN32_PROC

SetConsoleCtrlHandler(ctrlc_handler, TRUE );

#elif defined(HAVE_FORKEXEC)

// No SIGCHLD. Let the servicesubproc handle its children.

signal(SIGPIPE, SIG_IGN);

#endif


init_transport_registration();

=====>system/core/adb/transport.c

void init_transport_registration(void)

{

int s[2];

if(adb_socketpair(s)){

fatal_errno("cannot opentransport registration socketpair");

}

transport_registration_send =s[0];

transport_registration_recv =s[1];

fdevent_install(&transport_registration_fde,

transport_registration_recv,

transport_registration_func,

0);

fdevent_set(&transport_registration_fde, FDE_READ);

}

====>system/core/adb/transport.c

static voidtransport_registration_func(int _fd, unsigned ev, void *data)

{

tmsg m;

adb_thread_t output_thread_ptr;

adb_thread_t input_thread_ptr;

int s[2];

atransport *t;

fdevent_install(&(t->transport_fde),

t->transport_socket,

transport_socket_events,

t);

=====>system/core/adb/transport.c

static void transport_socket_events(intfd, unsigned events, void *_t)

{

atransport *t = _t;

D("transport_socket_events(fd=%d,events=%04x,...)\n", fd, events);

if(events & FDE_READ){

apacket *p = 0;

if(read_packet(fd, t->serial,&p)){

D("%s: failed to readpacket from transport socket on fd %d\n", t->serial, fd);

} else {

handle_packet(p,(atransport *) _t);

}

}

}

=====>system/core/adb/adb.c

void handle_packet(apacket *p,atransport *t)

{

asocket *s;

D("handle_packet()%c%c%c%c\n", ((char*) (&(p->msg.command)))[0],

((char*)(&(p->msg.command)))[1],

((char*)(&(p->msg.command)))[2],

((char*)(&(p->msg.command)))[3]);

print_packet("recv", p);

case A_OPEN: /* OPEN(local-id, 0,"destination") */

if (t->online) {

char *name = (char*)p->data;

name[p->msg.data_length> 0 ? p->msg.data_length - 1 : 0] = 0;

s =create_local_service_socket(name);

if(s == 0) {

send_close(0,p->msg.arg0, t);

} else {

s->peer =create_remote_socket(p->msg.arg0, t);

s->peer->peer =s;

send_ready(s->id,s->peer->id, t);

s->ready(s);

}

}

=====>system/core/adb/sockets.c

asocket*create_local_service_socket(const char *name)

{

asocket *s;

int fd;

#if !ADB_HOST

if (!strcmp(name,"jdwp")){

returncreate_jdwp_service_socket();

}

if (!strcmp(name,"track-jdwp")){

returncreate_jdwp_tracker_service_socket();

}

#endif

fd = service_to_fd(name);

if(fd < 0) return 0;

s = create_local_socket(fd);

D("LS(%d): bound to '%s' via%d\n", s->id, name, fd);

#if !ADB_HOST

if ((!strncmp(name, "root:",5) && getuid() != 0)

|| !strncmp(name, "usb:",4)

|| !strncmp(name, "tcpip:",6)) {

D("LS(%d): enablingexit_on_close\n", s->id);

s->exit_on_close = 1;

}

#endif

======>system/core/adb/services.c

int service_to_fd(const char *name)

{

int ret = -1;

} else if(!HOST &&!strncmp(name, "shell:", 6)) {

if(name[6]) {

ret =create_subproc_thread(name + 6);

} else {

ret =create_subproc_thread(0);

}

======>system/core/adb/services.c

static int create_subproc_thread(constchar *name)

{

stinfo *sti;

adb_thread_t t;

int ret_fd;

pid_t pid;

if(name) {

ret_fd =create_subprocess(SHELL_COMMAND, "-c", name, &pid);

} else {

ret_fd =create_subprocess(SHELL_COMMAND, "-", 0, &pid);

}

D("create_subprocess()ret_fd=%d pid=%d\n", ret_fd, pid);

sti = malloc(sizeof(stinfo));

if(sti == 0) fatal("cannotallocate stinfo");

sti->func =subproc_waiter_service;

sti->cookie = (void*)pid;

sti->fd = ret_fd;


======>system/core/adb/services.c

static int create_subprocess(const char*cmd, const char *arg0, const char *arg1, pid_t *pid)

{

#ifdef HAVE_WIN32_PROC

D("create_subprocess(cmd=%s,arg0=%s, arg1=%s)\n", cmd, arg0, arg1);

fprintf(stderr, "error:create_subprocess not implemented on Win32 (%s %s %s)\n", cmd,arg0, arg1);

return -1;

#else /* !HAVE_WIN32_PROC */

char *devname;

int ptm;

ptm = unix_open("/dev/ptmx",O_RDWR); // | O_NOCTTY);

if(ptm < 0){

printf("[ cannot open/dev/ptmx - %s ]\n",strerror(errno));

return -1;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值