refer: 浅析linux开发工具adb具体实现
发布日期:2021-11-16 18:19:07 浏览次数:4 分类:技术文章

本文共 25030 字,大约阅读时间需要 83 分钟。

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

//===============================

adb启动shell用到的命令
export ADBHOST= 192. 168. 100. 2
adb kill - server
adb start- server
adb 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_registration
void 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_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端口5037的sock数据
                                    = = = 尝试连接到"tcp:5037" 上的client们 = = = local_socket_event_func
并将"tcp:5037" 这个sock添加到listener_list链表上
好了, 我们的server已经成功起来了, 来看一个命令交互: adb shell
1. 本地执行adb shell
adb 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;
    //}
    //在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,对于我们分析的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;
}
= = > int adb_connect( const char * service)
= = > int fd = _adb_connect( "host:version" ) ;
= = >
    else {
    // if server was running, check its version to make sure it is not out of date
        char buf[ 100] ;
        int n;
        int version = ADB_SERVER_VERSION - 1; //先置个非法值
        // if we have a file descriptor, then parse version result
        if ( fd > = 0) {
     if ( readx( fd, buf, 4) ) goto error ; //读取数据长度
         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 not support the version command
            if ( strcmp ( __adb_error, "unknown host service" ) ! = 0)
                return fd;
        }
        if ( version ! = ADB_SERVER_VERSION) {
//版本不匹配
     printf ( "adb server is out 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) ; //接受client的socket_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(&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) ; //接受client的socket_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, "Created local socket in create_local_socket /n");
    D( "LS(%d): created (fd=%d)/n" , s- > id, s- > fd) ;
    return s;
}
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) ;
    return s;
}
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//如果是一个驻留服务
    . . .
    //对于我们的adb shell命令将执行到下面
    s- > peer- > ready = local_socket_ready_notify;
    s- > peer- > close = local_socket_close_notify;
    s- > peer- > peer = 0;
        /* give him our transport and upref it */
    s- > peer- > transport = s- > transport;
    //对于我们的adb shell命令就是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_remote call /n" ) ;
    apacket * p = get_apacket( ) ;
    int len = strlen ( destination) + 1;
    if ( len > ( MAX_PAYLOAD- 1) ) {
        fatal( "destination oversized" ) ;
    }
    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 of running emulator instances */
    /* this is only done 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( int port)
{
    char buf[ 64] ;
    int fd = - 1;
    fd = socket_loopback_client( port, SOCK_STREAM ) ;
# if ADB_HOST
    if ( fd < 0) {
        const char * host = getenv ( "ADBHOST" ) ; //就是上面export ADBHOST=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]
        return 0;
    }
    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_transport向client管理的transport_list链表登记注册
    register_socket_transport( fd, "host" , ADB_LOCAL_TRANSPORT_PORT) ; //创建请求线程
= = > register_socket_transport
= = > register_transport
static void register_transport( atransport * transport)
{
    tmsg m;
    m. transport = transport;
    m. action = 1;
    D( "transport: %p registered/n" , transport) ;
    if ( transport_write_action( transport_registration_send, & m) ) {
        fatal_errno( "cannot write transport registration socket/n" ) ;
    }
}
这样与transport_registration_send配对的transport_registration_recv将接收到该数据, 并且调用已经注册好的transport_registration_func( ) 函数来进一步处理发送过去的数据,
= = > transport_registration_func
= = > transport_socket_events
= = > void handle_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通过pts从pty发出的数据都将通过ptm主pty发送到peer对应的fd,即pc连接到手机端的socket,然后通过网络转发到pc端, 相应的,由pc端下发过来的数据将通过建立的socket读取到,然后交由该socket对应的peer,即:ptmx主pty,进而将直接被传递到 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
    } else if ( ! 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
# if 0
    } 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, const char * arg0, const char * arg1)
{
# ifdef HAVE_WIN32_PROC
    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;
    pid_t pid;
//这里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;
//子进程建立自己的新session id来和父进程完全独立开[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 */
}
手机上的client adb执行server_socket_thread线程等待ADB_LOCAL_TRANSPORT_PORT端口发生连接请求,
pc机端执行
export ADBHOST= 192. 168. 100. 2
adb kill - server //杀死pc上的adb server
adb start- server // 重新启动adb server,打开时,将client_socket_thread==>local_connect连接192.168.100.2的 ADB_LOCAL_TRANSPORT_PORT端口,这样手机端的server_socket_thread线程将接收到 ADB_LOCAL_TRANSPORT_PORT端口上的socket数据,然后登记该port为transport端口到 transport_list链表上[luther.gliethttp]
adb shell //登录adb shell,打开/system/bin/sh在从pty上,该sh的0,1,2句柄都将dup2到pts从pty对应的子进程上,然后ptm主pty, 将作为ADB_LOCAL_TRANSPORT_PORT端口上收发到数据后的转发peer对应的fd目的句柄,所以这样pc端的数据将通过socket 发送到手机上的socket,手机上的socket处理函数local_socket_event_func==> local_socket_enqueue将从网络接收到的数据转发给peer,即:ptm主pty,进而被pts从pty接收,也就是传递给了将 0,1,2句柄dup2到pts从pty上的/system/bin/sh应用程序,由/system/bin/sh输出的结果通过pts从pty传递给 ptm主pty,然后ptm主pty,发送到peer对应的fd,即pc连接到手机端的socket,然后通过网络转发到pc端,adb的大体流程就是这 个样子,当然还有很多细节,以后有时间再慢慢研究了,嘿[luther.gliethttp]

 

 

 

Detail refer: http://blog.chinaunix.net/space.php?uid=20564848&do=blog&cuid=1807376

转载地址:https://blog.csdn.net/taoshengyang/article/details/6233166 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:refer: 浅析adb创建流程
下一篇:转:linux的命令

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月15日 04时19分03秒