Android系統有監控程序異常退出的機制,這即是本文要講述得debuggerd守護進程。當發生native crash或者主動調用debuggerd時,會輸出進程相關的狀態信息到文件或者控制檯。輸出的debuggerd數據 保存在文件/data/tombstones/tombstone_XX
,該類型文件個數上限位10個,當超過期則每次覆蓋時間最老的文件。android
針對進程出現的不一樣的狀態,Linux kernel會發送相應的signal給異常進程,捕獲signal並對其作相應的處理(一般動做是退出異常進程)。而Android在這機制的前提下,經過攔截這些信號來dump進程信息,方便開發人員調試分析。socket
debuggerd守護進程會打開socket服務端,當須要調用debuggerd服務時,先經過客戶端進程向debuggerd服務端創建socket鏈接,而後發送不一樣的請求給debuggerd服務端,當服務端收到不一樣的請求,則會採起相應的dump操做。ionic
接下來從源碼角度來探索debuggerd客戶端和服務端的工做原理。函數
能夠做爲debuggerd的client端的進程主要有幾種:fetch
1. 異常的C/C++程序ui
這種程序由bionic的linker安裝異常信號的處理函數,當程序產生異常信號時,進入信號處理函數,與debuggerd創建。spa
2. debuggerd程序線程
debuggerd能夠在控制檯中以命令debuggerd -b [<tid>]啓動 ,而後與debuggerd daemon創建鏈接。這樣debuggerd能夠在不中斷進程執行的狀況下dump由tid指定的進程的信息。debug
3. dumpstate調試
控制檯中運行命令dumpstate,並指定必要的參數,命令中會調用dump_backtrace_to_file與debuggerd交互。
產生異常信號的C/C++程序與debuggerd創建鏈接後,debuggerd將進程信息dump到tombstone_XX文件中保存到/data/tombstone/文件夾下。可經過查看tombstone_XX分析異常進程的堆棧信息。
在控制檯中以命令debuggerd -b [<tid>]啓動。若是加上-b參數,則由tid指定的進程的信息將dump到控制檯上,不然dump到tombstone文件中。控制檯中運行命令callstack/dumpstate,進程信息會寫入這兩個命令指定的文件中。
---------------------
debuggerd -b <tid> debuggerd <tid>
經過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<pid_t>::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}