一、概述
Android系统有监控程序异常退出的机制,这便是本文要讲述得debuggerd守护进程。当发生native crash或者主动调用debuggerd时,会输出进程相关的状态信息到文件或者控制台。输出的debuggerd数据 保存在文件/data/tombstones/tombstone_XX
,该类型文件个数上限位10个,当超过时则每次覆盖时间最老的文件。针对进程出现的不同的状态,Linux kernel会发送相应的signal给异常进程,捕获signal并对其做相应的处理(通常动作是退出异常进程)。而Android在这机制的前提下,通过拦截这些信号来dump进程信息,方便开发人员调试分析。
debuggerd守护进程会打开socket服务端,当需要调用debuggerd服务时,先通过客户端进程向debuggerd服务端建立socket连接,然后发送不同的请求给debuggerd服务端,当服务端收到不同的请求,则会采取相应的dump操作。接下来从源码角度来探索debuggerd客户端和服务端的工作原理。
二、debuggerd客户端
1 2 |
debuggerd -b <tid> debuggerd <tid> |
通过adb执行上面的命令都能触发debuggerd进行相应的dump操作,其中参数-b`表示在控制台中输出backtrace,参数tid表示的是需要dump的进程或者线程id。这两个命令的输出结果相差较大,下面来一步步分析看看这两个命令分别能触发哪些操作,执行上述任一命令都会调用debuggerd的main方法()。
2.1 main
[-> /debuggerd/debuggerd.cpp]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
int main(int argc, char** argv) { ... bool dump_backtrace = false; bool have_tid = false; pid_t tid = 0; //参数解析backtrace与tid信息 for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-b")) { dump_backtrace = true; } else if (!have_tid) { tid = atoi(argv[i]); have_tid = true; } else { usage(); return 1; } } //没有指定tid则直接返回 if (!have_tid) { usage(); return 1; } //【见小节2.2】 return do_explicit_dump(tid, dump_backtrace); } |
对于debuggerd命令,必须指定线程tid,否则不做任何操作,直接返回。
2.2 do_explicit_dump
[-> /debuggerd/debuggerd.cpp]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
static int do_explicit_dump(pid_t tid, bool dump_backtrace) { fprintf(stdout, "Sending request to dump task %d.\n", tid); if (dump_backtrace) { fflush(stdout); //输出到控制台【见小节2.3】 if (dump_backtrace_to_file(tid, fileno(stdout)) < 0) { fputs("Error dumping backtrace.\n", stderr); return 1; } } else { char tombstone_path[PATH_MAX]; //输出到tombstone文件【见小节2.4】 if (dump_tombstone(tid, tombstone_path, sizeof(tombstone_path)) < 0) { fputs("Error dumping tombstone.\n", stderr); return 1; } fprintf(stderr, "Tombstone written to: %s\n", tombstone_path); } return 0; } |
dump_backtrace等于true代表的是输出backtrace到控制台,否则意味着输出到tombstone文件。
2.3 dump_backtrace_to_file
[-> libcutils/debugger.c]
1 2 3 4 5 6 7 8 9 ative crash或者主动调用debuggerd时,会输出进程相关的状态信息到文件或者控制台。输出的debuggerd数据 保存在文件 /data/tombstones/tombstone_XX ,该类型文件个数上限位10个,当超过时则每次覆盖时间最老的文件。针对进程出现的不同的状态,Linux kernel会发送相应的signal给异常进程,捕获signal并对其做相应的处理(通常动作是退出异常进程)。而Android在这机制的前提下,通过拦截这些信号来dump进程信息,方便开发人员调试分析。
debuggerd守护进程会打开socket服务端,当需要调用debuggerd服务时,先通过客户端进程向debuggerd服务端建立socket连接,然后发送不同的请求给debuggerd服务端,当服务端收到不同的请求,则会采取相应的dump操作。接下来从源码角度来探索debuggerd客户端和服务端的工作原理。 二、debuggerd客户端
通过adb执行上面的命令都能触发debuggerd进行相应的dump操作,其中参数-b`表示在控制台中输出backtrace,参数tid表示的是需要dump的进程或者线程id。这两个命令的输出结果相差较大,下面来一步步分析看看这两个命令分别能触发哪些操作,执行上述任一命令都会调用debuggerd的main方法()。 2.1 main[-> /debuggerd/debuggerd.cpp]
对于debuggerd命令,必须指定线程tid,否则不做任何操作,直接返回。 2.2 do_explicit_dump[-> /debuggerd/debuggerd.cpp]
dump_backtrace等于true代表的是输出backtrace到控制台,否则意味着输出到tombstone文件。 2.3 dump_backtrace_to_file[-> libcutils/debugger.c]
|