android 中断处理流程,Android P的native crash处理流程

本文详细介绍了Android系统的debuggerd守护进程如何监控并处理程序异常退出,包括当C/C++程序崩溃时如何生成tombstone文件,以及如何通过命令行工具如debuggerd-b和dumpstate与debuggerd交互来获取进程信息。通过分析debuggerd客户端和服务端的源码,揭示了debuggerd如何捕获信号、dump进程信息以及如何通过socket通信实现服务调用。
摘要由CSDN通过智能技术生成

一、概述

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的client端的进程主要有几种:

1.       异常的C/C++程序

这种程序由bionic的linker安装异常信号的处理函数,当程序产生异常信号时,进入信号处理函数,与debuggerd建立。

2.       debuggerd程序

debuggerd可以在控制台中以命令debuggerd -b []启动 ,然后与debuggerd daemon建立连接。这样debuggerd可以在不中断进程执行的情况下dump由tid指定的进程的信息。

3.       dumpstate

控制台中运行命令dumpstate,并指定必要的参数,命令中会调用dump_backtrace_to_file与debuggerd交互。

产生异常信号的C/C++程序与debuggerd建立连接后,debuggerd将进程信息dump到tombstone_XX文件中保存到/data/tombstone/文件夹下。可通过查看tombstone_XX分析异常进程的堆栈信息。

在控制台中以命令debuggerd -b []启动。如果加上-b参数,则由tid指定的进程的信息将dump到控制台上,否则dump到tombstone文件中。控制台中运行命令callstack/dumpstate,进程信息会写入这两个命令指定的文件中。

---------------------

二、debuggerd客户端

debuggerd -b

debuggerd

通过adb执行上面的命令都能触发debuggerd进行相应的dump操作,其中参数-b表示在控制台中输出backtrace,参数tid表示的是需要dump的进程或者线程id。这两个命令的输出结果相差较大,下面来一步步分析看看这两个命令分别能触发哪些操作,执行上述命令都会调用debuggerd的main方法()。

2.1 main

/system/core/debuggerd/debuggerd.cpp

此处就是根据输入的参数给出提示,如果输入的参数没有问题就会执行debuggerd_trigger_dump函数

58int main(int argc, char* argv[]) {

59 if (argc <= 1) usage(0);

60 if (argc > 3) usage(1);

61 if (argc == 3 && strcmp(argv[1], "-b") != 0 && strcmp(argv[1], "--backtrace") != 0) usage(1);

62 bool backtrace_only = argc == 3; //如果是有三个参数,则仅dumptrace,否则生成tombstone

63

64 pid_t pid;

65 if (!android::base::ParseInt(argv[argc - 1], &pid, 1, std::numeric_limits::max())) {

66 usage(1);

67 }

68

69 if (getuid() != 0) {

70 errx(1, "root is required");

71 }

72

73 // Check to see if the process exists and that we can actually send a signal to it.

74 android::procinfo::ProcessInfo proc_info;

75 if (!android::procinfo::GetProcessInfo(pid, &proc_info)) {

76 err(1, "failed to fetch info for process %d", pid);

77 }

78

79 if (proc_info.state == android::procinfo::kProcessStateZombie) {

80 errx(1, "process %d is a zombie", pid);

81 }

82

83 if (kill(pid, 0) != 0) {

84 err(1, "cannot send signal to process %d", pid);

85 }

86

87 unique_fd piperead, pipewrite;

88 if (!Pipe(&piperead, &pipewrite)) {

89 err(1, "failed to create pipe");

90 }

91

92 std::thread redirect_thread = spawn_redirect_thread(std::move(piperead));

93 if (!debuggerd_trigger_dump(pid, backtrace_only ? kDebuggerdNativeBacktrace : kDebuggerdTombstone,

94 0, std::move(pipewrite))) {

95 redirect_thread.join();

96 errx(1, "failed to dump process %d", pid);

97 }

98

99 redirect_thread.join();

100 return 0;

101}

system/core/debuggerd/client/debuggerd_client.cpp

bool debuggerd_trigger_dump(pid_t pid, DebuggerdDumpType dump_type, unsigned int timeout_ms,

unique_fd output_fd) {

//创建socket

97 sockfd.reset(socket(AF_LOCAL, SOCK_SEQPACKET, 0));

98 if (sockfd == -1) {

99 PLOG(ERROR) << "libdebugger_client: failed to create socket";

100 return false;

101 }

102

//连接服务端

103 if (socket_local_client_connect(set_timeout(sockfd.get()), kTombstonedInterceptSocketName,

104 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET) == -1) {

105 PLOG(ERROR) << "libdebuggerd_client: failed to connect to tombstoned";

106 return false;

107 }

124int socket_local_client_connect(int fd, const char* name, int namespaceId, int /*type*/) {

125 struct sockaddr_un addr;

126 socklen_t alen;

127 int err;

128

129 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);

130

131 if (err < 0) {

132 goto error;

133 }

134

135 if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {

136 goto error;

137 }

138

139 return fd;

140

141error:

142 return -1;

143}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值