本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!