Android 异常问题分析
1. Introduction
解決問題通常分為以下幾個步驟:
a) 確定問題,這是個什么樣的問題,有什么外在表現(xiàn);
b) 分析問題,根據(jù)log里面的蛛絲馬跡,定位出問題的原因;
c) 對癥下藥,盡量用最少的代碼解決問題,并確保不會引入新的問題;
d) 驗證修改,把自己的修改導(dǎo)入,確保自己的修改起了作用,并已經(jīng)徹底解決了問題,同時觀察是否引入新的問題;
此文檔主要面對的是幾類問題:
a) 重啟;
b) 死機(定屏);
c) 開機;
d) 黑屏;
下面會介紹各個問題,但基本只會從理論上介紹如何分析,所以不要期望看了這個文檔,你就能解決問題,這就像抓魚一樣,知道了如何抓魚,不代表你能抓得到魚;
2. 重啟問題
重啟問題分為兩類,一類是內(nèi)核重啟(包含Modem重啟),一類是上層重啟,如何區(qū)分?
如果有震動,那么就是內(nèi)核重啟,反之則是上層重啟;如果不記得有無震動,也可以通過開機時間來判斷,設(shè)置里面可以看開機經(jīng)過了多少時間,dmesg的輸出也有時間標(biāo)簽;還可以通過ps看進程號來判斷,如果zygote,servicemanager等的進程號比較小(一般100左右),那么通常是內(nèi)核重啟,否則就是上層重啟;如果你沒有看到現(xiàn)場,就只能通過Log來判斷了,后面會說到。
2.1 上層重啟
對于上層導(dǎo)致的重啟,這個比較普遍,一般有watch dog導(dǎo)致的重啟,需要進一步分析anr,一般是應(yīng)用死鎖導(dǎo)致的問題,很遺憾這里沒有例子;還有一種常見的問題就是native crash。重啟問題需要關(guān)注的就是時間點,一般在重啟之前一定有異常的log,往上繼續(xù)查找出現(xiàn)的異常,通常不遠處就是系統(tǒng)重啟的原因,并會打印出具體的棧信息。
如果是watch dog觸發(fā)的重啟,就需要分析anr里面的文件traces.txt,如果前面的進程名字不是system_server,通常意味著這個anr已經(jīng)被覆蓋了,這時候需要去dropbox里面找到對應(yīng)時間的文件,里面會保留下來;如果是system_server,就搜索ServerThread,這個是主線程,里面會告訴你它阻塞在了什么地方,然后順著它阻塞的路徑,一直追,就可以找到真正觸發(fā)系統(tǒng)阻塞的原因,通過棧信息,找到具體的文件,函數(shù),并聯(lián)系上下文,猜測出可能的路徑;這里是非常需要靈感的地方,不同的情景不同的原因,基本上沒有一個萬能的方法,全靠分析者自己的造化。
如果是native crash引發(fā),當(dāng)發(fā)生native crash的時候,一般在tombstone目錄下都能找到記錄。native調(diào)用棧一般都是在tombstone或者applogcat-log中打印出來。會有類似以下的log信息出現(xiàn)。
pid: 2363,tid: 2756, name: rild >>> /system/bin/rild <<<
signal 11(SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
檢查發(fā)生錯誤的類型,比如SIGSEGV、SIGBUS、SIGPIPE等,這里是SIGSEGV表示地址錯誤,那就檢查訪問地址。
這里有一個上層導(dǎo)致的重啟例子:
pid: 2363,tid: 2756, name: rild >>> /system/bin/rild <<<
signal 11(SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
r0 00000000r1 00000000 r2 1e7c32c2 r3 00000000
r4 b6d65565r5 b6d561a4 r6 00000000 r7 00000000
r8 b6d6be1cr9 b6b25cf8 sl b6d58e17 fp b6d6c1e8
ip b6d6beecsp b6b25a08 lr b6d3be41 pc b6f79140 cpsr 600f0030
d0676f6c522d657352 d1 6464615f79617749
d272207473756a204c d3 756e2074726f705f
d4002d00650074006c d5 007000750067006c
d6002e00730075006c d7 006b002e006f0063
d80000000000000000 d9 0000000000000000
d100000000000000000 d11 0000000000000000
d120000000000000000 d13 0000000000000000
d140000000000000000 d15 0000000000000000
d164150c82e3d2f1aa0 d17 0000000000000000
d18 41b7ccaa7c000000d19 0000000000000000
d200000000000000000 d21 0000000000000000
d220000000000000000 d23 0000000000000000
d240000000000000000 d25 0000000000000000
d260000000000000000 d27 0000000000000000
d280000000000000000 d29 0000000000000000
d30 0000000000000000d31 0000000000000000
scr 00000010
backtrace:
#00 pc00023140 /system/lib/libc.so (strlen+83)
#01 pc00015e3d /system/lib/libbalong-ril.so
#02 pc0001a1a3 /system/lib/libbalong-ril.so
#03 pc0001a903 /system/lib/libbalong-ril.so (on_data_call_list_changed+42)
#04 pc0002dffd /system/lib/libbalong-ril.so
#05 pc0000d410 /system/lib/libc.so (__thread_entry+72)
#06 pc0000d5a8 /system/lib/libc.so (pthread_create+240)
#07 pc00001014 [heap]
2.2 Modem重啟
關(guān)鍵log: sys rebootreason: Software EXCE CP
出現(xiàn)內(nèi)核重啟問題,首先應(yīng)該看看是不是Modem重啟,在目前發(fā)現(xiàn)的重啟問題來看,大部分是Modem導(dǎo)致的,當(dāng)然隨著版本的穩(wěn)定,現(xiàn)在也比較少了。
相關(guān)問題log:
06-0915:29:00.746 <6>[17425.253448] [1198.0, rdr_init_thread] rdr:sys rebootreason: Software EXCE CP
06-0915:29:00.748 <6>[17425.271850] [1198.0, rdr_init_thread] rdr:we shouldsave file to emmc before reboot!
06-0915:29:01.774 <6>[17426.294281] [1198.1, rdr_init_thread] save resetlog:rdr:system reboot reason: Software EXCE CP
06-0915:29:11.739 <6>[17436.260955] [1198.2, rdr_init_thread] we need rebootnow ...
06-09 15:29:14.645<6>[17439.164001] [1198.3, rdr_init_thread] sysreboot reason: SoftwareEXCE AP, tick: 20140609072914_17857.690150, systemError para: ModId=0x82000006,Arg1=5, Arg2=0
06-0915:29:14.648 <6>[17439.169677] [1198.3, rdr_init_thread] rdr:we shouldsave file to emmc before reboot!
06-0915:29:15.599 <6>[17440.122100] [1198.0, rdr_init_thread] save resetlog:sysreboot reason: Software EXCE AP, tick: 20140609072914_17857.690150
2.3 內(nèi)核重啟
關(guān)鍵log:sysreboot reason: Software EXCE AP
導(dǎo)致內(nèi)核重啟的原因主要是以下兩種:
1、代碼異常直接主動panic、被動panic(一般出現(xiàn)了踩了內(nèi)存、非法指針等致命錯誤)
2、硬件狗復(fù)位
內(nèi)核檢測到異常,直接調(diào)用BUG函數(shù)觸發(fā)panic,這里的BUG函數(shù)是一個宏定義,最終會調(diào)用panic函數(shù)打印出調(diào)用棧,同時導(dǎo)致手機重啟。在kmseg中能看到oops字串和backtrace調(diào)用棧,另外會生成dontpanic/APANIC_CONSOLE和dontpanic/APANIC_THREAD兩個文件,前者能看出引起重啟的時刻每個核的調(diào)用棧,后者能看出重啟時刻所有線程的調(diào)用棧信息。
panic信息位于apanic_console的末段,首先的找到panic信息的有關(guān)描述。通過分析堆棧信息可以找到問題的根因。
如果是因為指針異常一般會有以下log信息:
Unable tohandle kernel NULL pointer dereference at virtual address 00000000
踩內(nèi)存log一般如下:
Unable tohandle kernel paging request at virtual address 656d616e
踩內(nèi)存問題一般很難定位,需要往前追溯看看有沒有異常的log,警告也需要重點關(guān)注。例如:字符串操作不當(dāng),引起的內(nèi)存越界問題。
3. 開機問題
這個問題的現(xiàn)象就是機器一直在開機界面,有兩種情況,一是靜態(tài)LOGO;一種是動態(tài)LOGO。
3.1 靜態(tài)的LOGO的情景
1、硬件故障,基本adb都無法連接上,需要硬件同事幫忙分析。
主要可能出現(xiàn)的硬件故障有:
CPU(包括L1,L2 cache)、DDR、 EMMC、 BUS 、PMU(電源管理)…
2、內(nèi)核(或BOOT)故障,不能連接adb,需要連接串口分析。
3、zygote反復(fù)重啟引起的問題,導(dǎo)致systemserver沒有起來。
4、如果不是以上問題,就需要分析內(nèi)核日志。
3.2 停在動態(tài)的LOGO界面
一般是因為開機時因為各種異常導(dǎo)致系統(tǒng)應(yīng)用層面出現(xiàn)崩潰,一般還是可以正常使用adb shell的。
1、如果動畫界面,是否卡死Systemserver。
2、反復(fù)播放動畫,是否Systemserver反復(fù)重啟。
3、關(guān)注內(nèi)核死鎖問題。關(guān)注dmesg_sysrq.txt文件,文件的尾部都有SYSRQ信息,會打印出當(dāng)前的D進程狀態(tài),可以逐個查看是否有死鎖的情況。
4. 死機(定屏)問題
如何判斷一個問題是否是一個死機問題?
對于Android平臺,從現(xiàn)象上說,就是屏幕以及按鍵沒有任何反應(yīng),給此設(shè)備打電話,也不會有任何反應(yīng),但是對于分析者來說,是插入USB線沒有反應(yīng),也就是Windows的設(shè)備管理器,不會因為插USB線而出來新的設(shè)備(如果屏幕按鍵無反應(yīng),但出現(xiàn)了新的設(shè)備,那這個是后面要說的白屏問題)
需要收集哪些現(xiàn)場?
對于這類問題,我們當(dāng)前的策略通常是需要抓取串口log,也就是說,如果出現(xiàn)這種情況的時候,沒有連接串口,基本上是無能為力的(Google默認(rèn)提供了一種機制叫做last_kmsg,似乎是可以在重啟的時候把上次crash的kernel log寫到/proc/last_kmsg里面去),如果連接了串口,通過判斷串口是否有輸出,可以定位出內(nèi)核到底死了沒有,如果是kernel死,會打印出kernel crash的棧信息以及寄存器信息,可以根據(jù)棧信息,定位出是什么模塊導(dǎo)致的;
簡單點說,如果是對于死機問題,我們需要抓取串口log。
如何分析:
如果一定要有秘籍的話,那么就是認(rèn)真觀察死之前的遺言!
通常都會有棧信息出來,根據(jù)棧信息就可以看到是那個函數(shù)引起的,所以相對來說好定位,當(dāng)然也出現(xiàn)過出事的函數(shù)只是替罪羊,真正的罪魁禍?zhǔn)自谀缓蟮那闆r,但是,打印的信息都會做出一定的暗示,透過現(xiàn)象看本質(zhì),不輕易下結(jié)論。
給出一些判斷建議:
1、連接不了adb,也沒有按鍵中斷,只能連接jtag調(diào)試了;
2、連接不了adb,有按鍵中斷,連接串口、按鍵觸發(fā)panic;
3、可以連接adb,觸發(fā)SYSRQ,檢查是否內(nèi)核異??ㄋ?#xff0c;OOM(分析卡死原因、內(nèi)存是否真的少了)。
5、getevent是否上報,找出不上報原因;
6、InputDispatch出現(xiàn)異常,隊列爆了,無法正常分發(fā)事件;
7、界面無刷新,分析surfacefinger、LCD驅(qū)動(顯示異常定位)。
5. 黑屏問題
黑屏問題,很好確認(rèn),屏變黑了,撥電話沒反應(yīng),并且維持這個狀態(tài)很長一段時間,如果插入USB沒有反應(yīng),那么它就是一個死機問題,請看死機部分;如果有反應(yīng),那么它就是我們這里說的黑屏問題了;
正常情況下,都應(yīng)該是系統(tǒng)重啟,所以它的情報搜集以及分析過程和上面說的重啟是一樣的!(但是,有種黑屏的現(xiàn)象是觸屏,按鍵都無法響應(yīng),但是打電話還有反應(yīng),是我們說的點不亮的問題,這個問題通常是在睡眠或者喚醒的時候被阻塞住了,它的分析,比較復(fù)雜,需要在內(nèi)核里的睡眠喚醒的核心加大量的信息來定位,通常是suspend的線程被阻塞了,導(dǎo)致后面的late_resume函數(shù),也就是點亮lcd的動作一直沒有被觸發(fā)執(zhí)行,因為它們是放在同一個work queue suspend_work_queue來做的,需要去檢查為什么前面的suspend被阻塞了,當(dāng)然,如果你對內(nèi)核非常的熟悉,也能從串口或者dmesg信息里面看出蛛絲馬跡,然后做對應(yīng)的測試,這里就不討論了)。
6. 總結(jié)
1、當(dāng)我們被測試部的同事急急忙忙的叫去看現(xiàn)場的時候,通常并不知道這是個什么樣的現(xiàn)象,所以要盡量抓取足夠多的信息。尤其是需要知道出現(xiàn)問題的時間點。
2、根據(jù)現(xiàn)場,初步判斷是死機,重啟,白屏中的哪種?
3、根據(jù)第二步的判斷,如果是內(nèi)核死機,則重點查看dmesg信息;如果是上層死機,重點查看tombstone,bugreport,logcat,anr;如果是內(nèi)核重啟,重點查看dmesg信息;如果是上層重啟,重點查看logcat,anr
4、然后就根據(jù)面的介紹,逐個分析,如果還無法定位的話,就需要添加自己的打印信息。
?
總結(jié)
以上是生活随笔為你收集整理的Android 异常问题分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HiJson,一个json格式化查看工具
- 下一篇: android java 调试快捷键_最