ADB(二)_ADBD_main()函数代码梳理

前言

前文

ADB(一)_概况了解

前面我们对ADB从整体上进行了简单的概括梳理,我们对adb的了解应该比日常开发了解的更多了。现在就需要从局部对adb进行分析,了解它组成部分的具体工作原理是怎么样的,相互之间又是怎么进行交互的。

ADBD (ADB daemon)

在上一篇内容里我们知道adbd主要作用是连接ADB Server 和android device或者仿真器并为在开发者主机上的client提供一些服务.那我们就先从运行在Android device、Emulator上面的adbd程序入手。

1. ADBD代码说明

由于程序是由C++在底层编写的。那我们就从它的main()函数入口来了解adbd的启动流程是怎样的。
这里还是先摆出Android.mk文件中adbd的编译部分。也为接下来的代码追踪提供线索。


# adbd device daemon
# =========================================================
include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
    daemon/main.cpp \
    daemon/mdns.cpp \
    services.cpp \
    file_sync_service.cpp \
    framebuffer_service.cpp \
    remount_service.cpp \
    set_verity_enable_state_service.cpp \
    shell_service.cpp \
    shell_service_protocol.cpp \

LOCAL_CFLAGS := \
    $(ADB_COMMON_CFLAGS) \
    $(ADB_COMMON_linux_CFLAGS) \
    -DADB_HOST=0 \
    -D_GNU_SOURCE \
    -Wno-deprecated-declarations \
    
LOCAL_CFLAGS += -DALLOW_ADBD_NO_AUTH=$(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),1,0)

ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1
endif

LOCAL_MODULE := adbd

LOCAL_FORCE_STATIC_EXECUTABLE := true

LOCAL_SANITIZE := $(adb_target_sanitize)
LOCAL_STRIP_MODULE := keep_symbols
LOCAL_STATIC_LIBRARIES := \
    libadbd \
    libasyncio \
    libavb_user \
    ...
include $(BUILD_EXECUTABLE)

虽然有Android.mk明确了adb和adbd分别编译的代码文件。但是有一些文件是adb和adbd共同使用的,也就是说在同一份代码既需要在adb中使用,也需要在adbd中使用,这时候,C++就使出了它常用的宏定义的方法了。利用ADB_HOST标志【ADB_HOST说明是在主机端运行,不在Android devices运行】来选择了,我们在源码中也常会看见以下这样的宏定义:

...
#if ADB_HOST
...//代码块①
#endif
...

如果ADB_HOST为真,那么接下来要走的就是代码块①,否则就不走代码块①。

2. adbd初始化说明

在main()函数的一开始,就出现一个getopt_long()函数,这是一个解析命令行的函数,然后就会调用close_stdin(),用来关闭标准输入;

int main(int argc, char** argv) {
	 ...
    int c = getopt_long(argc, argv, "", opts, &option_index);
    ...
    close_stdin();
    debuggerd_init(nullptr);
    adb_trace_init(argv);
    D("Handling main()");
    return adbd_main(DEFAULT_ADB_PORT);
}

adbd_main 函数调动流程
如上图所示,就是adbd的main()函数的调用流程;下面就上述的函数调用来梳理一下adbd启动时做了哪些事:

2.1 getopt_long

首先这个getopt_long()函数是系统提供的,主要作用就是用来解析命令行参数,主要是根据命令行参数给root_seclabeladb_device_banner这两个变量赋值,root_seclabel是可以理解为安全标签的意思,是adbd的权限说明,adb_device_banner可以理解为是说明设备是android设备还是主机。

...
case 's':
     root_seclabel = optarg;
     break;
case 'b':
     adb_device_banner = optarg;
     break;
...
2.2 close_stdin

close_stdin()函数内部的实现如下代码所示,

...
constexpr char kNullFileName[] = "/dev/null";
#endif
void close_stdin() {
    int fd = unix_open(kNullFileName, O_RDONLY);
    if (fd == -1) {
        fatal_errno("failed to open %s", kNullFileName);
    }

    if (TEMP_FAILURE_RETRY(dup2(fd, STDIN_FILENO)) == -1) {
        fatal_errno("failed to redirect stdin to %s", kNullFileName);
    }
    unix_close(fd);
}
...

在这里,我们主要关注一下这个dup2()函数;这个dup2()函数原型是int dup2(int oldfd, int newfd);

/* Standard file descriptors.  */
#define	STDIN_FILENO	0	/* Standard input.  */
#define	STDOUT_FILENO	1	/* Standard output.  */
#define	STDERR_FILENO	2	/* Standard error output.  */

在这里dup2(fd, STDIN_FILENO)的意思是,newfd指向oldfd句柄指向的文件描述符结构,即原本是指向标准输出文件描述结构体的STDIN_FILENO指向标准输出文件指向了"/dev/null",这样一来,原本从显示器终端输入文件输入的数据从改从/dev/null文件输入了;

2.3 debuggerd_init

Android 提供了一个程序异常退出的诊断daemon debuggerd。此进程可以侦测到程序崩溃,并将崩溃时的进程状态信息输出到文件和串口中,以供开发人员分析调试使用。具体的工作原理此处就不深入,知道这是用于分析调试的就行。

2.4 adb_trace_init

adbd的adb_trace_init()函数的内部实现如下所示(这里我已经剔除了非adbd的代码部分):

std::string get_trace_setting() {
    return android::base::GetProperty("persist.adb.trace_mask", "");
}
....
void adb_trace_init(char** argv) {
    ...
    // Don't open log file if no tracing, since this will block
    // the crypto unmount of /data
    if (!get_trace_setting().empty()) {
        if (unix_isatty(STDOUT_FILENO) == 0) {
            start_device_log();
        }
    }
    ...
    android::base::InitLogging(argv, &AdbLogger);

    setup_trace_mask();

    VLOG(ADB) << adb_version();
}

在adbd的adb_trace_init(0函数中,首先通过获取系统设置来决定时候开始设备的log。然后调用setup_trace_mask()设置trace掩码;adb的trace设置来自adb_trace环境变量,而adbd来自系统属性persist.adb.trace_mask。就是说通过获取Android系统属性来设置trace。

2.5 adbd_main(DEFAULT_ADB_PORT);
#define DEFAULT_ADB_PORT 5037

adbd的默认通信端口是5037,adb_main()函数是main()函数最后调用,综合main()函数之前的调用,我们可以判断adbd的绝大部分工作应该都在adbd的adb_main()函数中。

如需进一步了解,请继续阅读:

ADB(三)_ADBD_adbd_main()函数代码梳理

发布了41 篇原创文章 · 获赞 35 · 访问量 4293

猜你喜欢

转载自blog.csdn.net/weixin_38140931/article/details/103872178