哈嘍,大家好,我是LittleG。
編程語(yǔ)言是工具,在實(shí)際工作中我們可能往往會(huì)用到一種編程語(yǔ)言工具或者多種編程語(yǔ)言工具才能實(shí)現(xiàn)一個(gè)完整功能的需求;尤其是在 Android 的開發(fā)過(guò)程中,從上層到底層,涉及 java、C++、C,而且目前看谷歌正在部署引入新的開發(fā)語(yǔ)言 Rust ,大有替代 C++ 和 C 部分功能實(shí)現(xiàn)的趨勢(shì);下一步,我們很有可能又得再多學(xué)習(xí)一門編程語(yǔ)言了。
在實(shí)際開發(fā)中,因?yàn)榻?jīng)常分析問(wèn)題,需要從上到下跟蹤一些代碼調(diào)用流程,所以就會(huì)有分別在?java、native、kernel 打印調(diào)用堆棧的需求;之前也都是零散的在用,今天花了一些時(shí)間,梳理了一下,記錄分享之。
正文
Android java、native、kernel打印堆棧常用方法總結(jié):
一、java
import android.util.Log; Log.e("LOG_TAG", "log info", Log.getStackTraceString(new Throwable())); //或者 android.util.Log.e("LOG_TAG", "log info", android.util.Log.getStackTraceString(new Throwable()));
二、native
//mk添加: LOCAL_SHARED_LIBRARIES += libutils libutilscallstack //頭文件添加: #include <log/log.h> #include <utils/CallStack.h> //在想調(diào)用Callstack的函數(shù)中加入如下代碼: android::CallStack callstack; callstack.update(); callstack.log("LOG_TAG", ANDROID_LOG_INFO, "xxxx");//LOG_TAG是TAG;xxxx是backtrace的前綴; //或者 android::CallStack stack("my_test");
三、kernel
#include "linux/printk.h" //常用dump_stack,打印堆棧信息 dump_stack(); //或者可用WARN_ON,其原型可以看到也是調(diào)了dump_stack,打印堆棧信息,不會(huì)OOPS; WARN_ON(xxxx == yyyy); #define WARN_ON(condition) do { / ? ? ?if (unlikely((condition)!=0)) { / ? ? ? ? ?printk("Badness in %s at %s:%d/n", __FUNCTION__, __FILE__,__LINE__); / ? ? ? ? ?dump_stack(); / ? ? } / } while (0) //如果想OOPS,可以使用 BUG_ON BUG_ON(bad_thing);
四、通過(guò) debuggerd命令 或者 tombstone機(jī)制獲取堆棧信息
1、使用debuggerd
命令:
root:/ # debuggerd -h usage: debuggerd [-bj] PID -b, --backtrace ? just a backtrace rather than a full tombstone -j ? ? ? ? ? ? ? ? collect java traces root:/ # debuggerd -b 1884
說(shuō)明:以上 1884 是 pid。正常情況,使用 debuggerd 并不會(huì)導(dǎo)致進(jìn)程異常退出。使用該命令時(shí),目標(biāo)進(jìn)程會(huì)收到一個(gè) SIGCHLD 信號(hào),系統(tǒng)默認(rèn)會(huì)忽略此信號(hào);但是如果目標(biāo)進(jìn)程捕獲了該信號(hào),因?yàn)樾盘?hào)會(huì)導(dǎo)致 kernel 可中斷任務(wù)(TASK_INTERRUPTIBLE)被喚醒,進(jìn)而可能導(dǎo)致用戶進(jìn)程一些系統(tǒng)調(diào)用(select、read、sleep 等)返回異常,此時(shí)如果不配合做一些處理,就可能導(dǎo)致進(jìn)程異常退出。
2、利用 tombstone
機(jī)制:
進(jìn)程?crash,即可觸發(fā)生成/data/tombstone?目錄文件,手動(dòng)導(dǎo)出即可??梢允褂妙愃啤?kill -11 ”的命令,注意確認(rèn)進(jìn)程本身沒(méi)有捕獲 SIGSEGV,不然就不會(huì)發(fā)生 crash 了 。
root:/ # kill -11 1884
說(shuō)明:以上 1884 是 pid。
附:kill 命令 signals
:
root:/ # kill -l 1 ?? HUP Hangup ? ? ? ? ? ? ? ? ? ? ? 2? ? INT Interrupt ? ? ? ? ? ? ? ? ? ? 3? ? QUIT Quit ? ? ? ? ? ? ? ? ? ? ? ? 4? ? ILL Illegal instruction ? ? ? ? ? 5? ? TRAP Trap ? ? ? ? ? ? ? ? ? ? ? ? 6? ? ABRT Aborted ? ? ? ? ? ? ? ? ? ? ? 7? ? BUS Bus error ? ? ? ? ? ? ? ? ? ? 8? ? FPE Floating point exception ? ? 9? ? KILL Killed ? ? ? ? ? ? ? ? ? ? ? 10 ? USR1 User signal 1 ? ? ? ? ? ? ? ? 11 ? SEGV Segmentation fault ? ? ? ? ? 12 ? USR2 User signal 2 ? ? ? 13 ? PIPE Broken pipe ? ? ? ? 14 ? ALRM Alarm clock ? ? ? ? 15 ? TERM Terminated ? ? ? ? ? 16? ?STKFLT Stack fault ? ? ? ? 17 ? CHLD Child exited ? ? ? ? 18 ? CONT Continue ? ? ? ? ? ? 19 ? STOP Stopped (signal) ? ? 20 ? TSTP Stopped ? ? ? ? ? ? 21 ? TTIN Stopped (tty input) 22 ? TTOU Stopped (tty output) 23 ? URG Urgent I/O condition ? ? 24 ? XCPU CPU time limit exceeded 25 ? XFSZ File size limit exceeded 26? ?VTALRM Virtual timer expired ? 27 ? PROF Profiling timer expired 28? ?WINCH Window size changed ? ? 29 ? IO I/O possible ? ? ? ? ? ? 30 ? PWR Power failure ? ? ? ? ? 31 ? SYS Bad system call ? ? ? ? 32 ? Signal 32 ? ? ? ? ? ? ? 33 ? Signal 33 ......
如果你有更好的方法和經(jīng)驗(yàn),歡迎交流,謝謝~