浅析linux开发工具adb具体实现
《再次浅析adb shell,pc daemon和手机daemon三者之间的数据交互流程》
《浅析adb创建流程》
//===============================
adb启动shell用到的命令
export ADBHOST=192.168.100.2
adb kill-server
adb start-server11:31:27
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;
}
《再次浅析adb shell,pc daemon和手机daemon三者之间的数据交互流程》
《浅析adb创建流程》
//===============================
adb启动shell用到的命令
export ADBHOST=192.168.100.2
adb kill-server
adb start-server11:31:27
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;
}