amg project oneF.A.T.E何时重启

Android的死机、重启问题分析方法_Android开发-织梦者
当前位置:&>&&>& > Android的死机、重启问题分析方法
Android的死机、重启问题分析方法
1.死机现象
1.1死机定义
当手机长时间无法再被用户控制操作时,我们称为死机。在这里我们强调长时间,如果是短时间,归结为性能问题。
1.2死机表现
*用户操作手机无任何响应,如触摸屏幕,按键操作等。
*手机屏幕黑屏,无法点亮屏幕。
*手机界面显示内容和用户输入不相干。
1.系统简图
当用户对手机进行操作时,对应的数据流将是下面一个概括的流程图
* HW如传感器,触摸屏(TP),物理按键(KP)等感知到用户操作后,触发相关的中断(ISR)传递给Kernel,Kernel相关的driver对这些中断进行处理后,转化成标准的InputEvent。
* UserSpace的System
Server中的Input
System则持续监听Kernel传递上来的原始InputEvent,对其进行进一步的处理后,变成上层APP可直接处理的Input
Event,如button点击,长按,滑动等等。
* APP对相关的事件进行处理后,请求更新相关的逻辑界面,而这个则由System
Server中的WMS等来负责。
*相关的逻辑界面更新后,则会请求SurfaceFlinger来产生FrameBuffer数据,SurfaceFlinger则会利用GPU等来计算生成。
* DisplaySystem/Driver则会将FrameBuffer中的数据更新显示出来,这样用户才能感知到他的操作行为。
2.可能死机的原因
原则上上面流程中,每一步出现问题,都可能引发死机问题。大的方面讲,可以分成硬件HW和软件SW两个层次,硬件HW不在我们的范围之内。
软件SW上,死机的原因可以分成两种:
(1). 逻辑行为异常
**逻辑判断错误
**逻辑设计错误
(2). 逻辑卡顿(block)
*死循环(Deadloop)
*死锁(Deadlock)
从具体的原因上将,可以进一步分成:
(1). InputDriver
*无法接收HW的中ISR,产生原始的InputEvent或者产生的InputEvent异常。
分析死机、触屏无响应的问题的时候,第一步要先看看有没有inputEvent上来,即有没有报点,各个平台inputEvent的设备节点都不一样,可以通过下面方法获取:
adb shellgetevent
这个命令下下去以后会在屏幕上输出当前设备的节点,可从name一行判断哪一个是TW,当然也可以在此时直接在屏幕上触摸看有没有时间上报,正常情况如下:
可以看出event2是触摸事件。
异常情况下触摸是没有事件上报的。
当然也可以直接下adb
shell getevent/dev/input/event2检查。
(2). InputSystem
无法监听Kernel传递上来的原始InputEvent,或者转换与传递异常。
(3). SystemLogic
无法正常响应InputSystem传递过来的InputEvent,或者响应出错。
(4).WMS/Surfaceflinger行为异常
WMS/ Surfaceflinger无法正确的对Window进行叠加转换
(5).Display System
无法更新Framebuffer数据,或者填充的数据错误
(6). LCMDriver
无法将Framebuffer数据显示在LCM上
对应硬件HW异常,经常见得的情况有:
* Memory& Memory Controller
2. 死机分析数据
死机分析,同样需要获取第一手的资料,方可分析问题.那么哪些数据可以用来分析死机呢?
大概的讲,可以分成空间数据和时间数据。空间数据,即当时现场环境,如有哪些process在运行,CPU的执行情况,memory的利用情况,以及具体的process的memory数据等。时间数据,即行为上的连续数据,比如某个Process在一段时间内执行了哪些操作,某段时间内CPU利用率的变化等。通常时空都是交融的,对应我们抓取log时往往也是。
Backtrace又分成Java
backtrace,Native
Backtrace,Kernel
Backtrace。它是分析死机的非常重要的手段,借助Backtrace,我们可以快速的知道,对应的process/thread在当时正在执行哪些动作,卡住哪里等。可以非常直观的分析死机现场。
1 Java Backtrace
Backtrace,我们可以知道当时Process的虚拟机执行状态。JavaBacktrace依靠SignalCatcher来抓取。
Googledefault: SignalCatcher catchs SIGQUIT(3),and
thenprint the java backtrace to /data/anr/trace.txt
MTKEnhance: SignalCatcher catchs SIGSTKFLT(16),and
thenprint the java backtrace to /data/anr/mtktrace.txt( After 6577.SP/ICS2.MP)
可以通过修改系统属性dalvik.vm.stack-trace-file改变trace文件路径,默认路径为/data/anr/traces.txt
1.1抓取的方式
一般进程出现无响应的问题,系统会发送SIGQUIT(3)信号给该进程,收到这个信号会,进程会将当前的调用栈打印在trace.txt文件里。
手动抓取进程的Backtrace方法如下:
adb remount
adb shellchmod 0777 data/anr
adb shellkill -3 pid
adb pull/data/anr
1.2JavaBacktrace解析
下面是一小段system
server的java
backtrace的开始
----- pid 682 at
18:04:53 -----
Cmd line: system_server
JNI: CheckJNIpins=4; globals=1484 (plus 50 weak)
DALVIK THREADS:
&main& prio=5 tid=1 NATIVE
| group=&main& sCount=1dsCount=0 obj=0x4193fde0 self=0x
| sysTid=682 nice=-2 sched=0/0cgrp=apps handle=
| state=S schedstat=(
44902 ) utm=4074 stm=711 core=0
at android.os.MessageQueue.nativePollOnce(NativeMethod)
at android.os.MessageQueue.next(MessageQueue.java:138)
at android.os.Looper.loop(Looper.java:150)
at com.android.server.ServerThread.initAndLoop(SystemServer.java:1468)
at com.android.server.SystemServer.main(SystemServer.java:1563)
at java.lang.reflect.Method.invokeNative(NativeMethod)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
at dalvik.system.NativeStart.main(NativeMethod)
我们一行一行来解析.
0#最开始是 -----PID at Time 然后接着 Cmd line: process name
1# the backtrace header: dvm thread :“DALVIK THREADS:”
2# thread name, java thread Priority, [daemon], DVM thread id, DVM thread status.
&main& -& mainthread -& activity thread
prio -& java threadpriority default is 5, (nice =0, linux thread priority 120),domain is [1,10]
DVMthread id, NOT linux thread id
DVM thread Status:
ZOMBIE, RUNNABLE, TIMED_WAIT, MONITOR, WAIT, INITALIZING,STARTING, NATIVE, VMWAIT, SUSPENDED,UNKNOWN
&main& prio=5 tid=1NATIVE
3# DVM thread status
group: default is “main”
Compiler,JDWP,Signal Catcher,GC,FinalizerWatchdogDaemon,FinalizerDaemon,ReferenceQueueDaemonare system group
sCount: thread suspend count
dsCount: thread dbg suspend count
obj: threadobj address
Sef: thread point address
group=&main& sCount=1dsCount=0 obj=0x4193fde0 self=0x
#5 Linux thread status
sysTId: linux thread tid
Nice: linux thread nice value
sched: cgroup policy/gourp id
cgrp: c group
handle: handle address
sysTid=682 nice=-2 sched=0/0cgrp=apps handle=
#6 CPU Schedstat
Schedstat (Run CPU Clock/ns, Wait CPU Clock/ns, Slice times)
utm: utime, user space time(jiffies)
stm: stime, kernel space time(jiffies)
Core now running in cpu.
state=S schedstat=(
44902 ) utm=4074 stm=711 core=0
#7-more CallStack
1.3几种常见的java
1.3.1ActivityThread正常状态的Backtrace
MessageQueue is empty,and
thread wait fornext message.
&main& prio=5 tid=1 NATIVE
| group=&main&sCount=1 dsCount=0 obj=0x4193fde0 self=0x
| sysTid=11559 nice=0sched=0/0 cgrp=apps/bg_non_interactive handle=
| state=S schedstat=(
7975 ) utm=100 stm=139 core=1
at android.os.MessageQueue.nativePollOnce(NativeMethod)
at android.os.MessageQueue.next(MessageQueue.java:138)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:5299)
at java.lang.reflect.Method.invokeNative(NativeMethod)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
at dalvik.system.NativeStart.main(NativeMethod)
1.3.2 JavaBacktrace Monitor case
SynchronizedLock:等待同步锁时的backtrace.
&AnrMonitorThread& prio=5tid=24 MONITOR
| group=&main&sCount=1 dsCount=0 obj=0x41fd80c8 self=0x551ac808
| sysTid=711 nice=0 sched=0/0cgrp=apps handle=
| state=S schedstat=(
6892 ) utm=160 stm=666 core=0
at com.android.server.am.ANRManager$AnrDumpMgr.dumpAnrDebugInfoLocked(SourceFile:~832)
- waiting to lock&0x& (a com.android.server.am.ANRManager$AnrDumpRecord) held bytid=20 (ActivityManager)
at com.android.server.am.ANRManager$AnrDumpMgr.dumpAnrDebugInfo(SourceFile:824)
at com.android.server.am.ANRManager$AnrMonitorHandler.handleMessage(SourceFile:220)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.os.HandlerThread.run(HandlerThread.java:61)
1.3.3执行JNI
code未返回,状态是native的情况
&WifiP2pService& prio=5tid=37 NATIVE
| group=&main&sCount=1 dsCount=0 obj=0x427a9910 self=0x55f088d8
| sysTid=734 nice=0 sched=0/0cgrp=apps handle=
| state=S schedstat=(
) utm=7 stm=2 core=1
#00 pc /system/lib/libc.so (epoll_wait+12)
#01 pc /system/lib/libutils.so (android::Looper::pollInner(int)+94)
#02 pc /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+92)
#03 pc 0006c96d/system/lib/libandroid_runtime.so(android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22)
#04 pc 0001eacc/system/lib/libdvm.so (dvmPlatformInvoke+112)
#05 pc 0004fed9/system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+484)
#06 pc 00027ea8/system/lib/libdvm.so
#07 pc /system/lib/libdvm.so (dvmMterpStd(Thread*)+76)
#08 pc /system/lib/libdvm.so (dvmInterpret(Thread*, Methodconst*, JValue*)+188)
#09 pc /system/lib/libdvm.so (dvmCallMethodV(Thread*, Methodconst*, Object*, bool, JValue*,std::__va_list)+340)
#10 pc /system/lib/libdvm.so (dvmCallMethod(Thread*, Methodconst*, Object*, JValue*, ...)+20)
#11 pc /system/lib/libdvm.so
#12 pc 0000dd40/system/lib/libc.so (__thread_entry+72)
at android.os.MessageQueue.nativePollOnce(NativeMethod)
at android.os.MessageQueue.next(MessageQueue.java:138)
at android.os.Looper.loop(Looper.java:150)
at android.os.HandlerThread.run(HandlerThread.java:61)
1.3.4执行object.wait等待状态
&AsyncTask #1& prio=5tid=33 WAIT
| group=&main&sCount=1 dsCount=0 obj=0x427a8480 self=0x56036b40
| sysTid=733 nice=10sched=0/0 cgrp=apps/bg_non_interactive handle=
| state=S schedstat=(
4229 ) utm=119 stm=75 core=0
at java.lang.Object.wait(NativeMethod)
- waiting on&0x427a8618& (a java.lang.VMThread) held by tid=33 (AsyncTask #1)
at java.lang.Thread.parkFor(Thread.java:1212)
at sun.misc.Unsafe.park(Unsafe.java:325)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2017)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:410)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1035)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1097)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:848)
1.3.5Suspend状态,通常表明是抓取backtrace时,当时还正在执行java代码,被强制suspend的情况
&FileObserver& prio=5tid=23 SUSPENDED
| group=&main&sCount=1 dsCount=0 obj=0x41fd1dc8 self=0x551abda0
| sysTid=710 nice=0 sched=0/0cgrp=apps handle=
| state=S schedstat=( ) utm=9 stm=4 core=0
#00 pc /system/lib/libc.so (__futex_syscall3+8)
#01 pc 000108cc/system/lib/libc.so (__pthread_cond_timedwait_relative+48)
#02 pc 0001092c/system/lib/libc.so (__pthread_cond_timedwait+64)
#03 pc 00055a93/system/lib/libdvm.so
#04 pc 0005614d /system/lib/libdvm.so(dvmChangeStatus(Thread*, ThreadStatus)+34)
#05 pc 0004ae7f/system/lib/libdvm.so
#06 pc /system/lib/libdvm.so
#07 pc /system/lib/libandroid_runtime.so
#08 pc 0008af9f/system/lib/libandroid_runtime.so
#09 pc 0001eacc/system/lib/libdvm.so (dvmPlatformInvoke+112)
#10 pc 0004fed9/system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+484)
#11 pc 00027ea8/system/lib/libdvm.so
#12 pc /system/lib/libdvm.so (dvmMterpStd(Thread*)+76)
#13 pc /system/lib/libdvm.so (dvmInterpret(Thread*, Methodconst*, JValue*)+188)
#14 pc /system/lib/libdvm.so (dvmCallMethodV(Thread*, Methodconst*, Object*, bool, JValue*, std::__va_list)+340)
#15 pc /system/lib/libdvm.so (dvmCallMethod(Thread*, Methodconst*, Object*, JValue*, ...)+20)
#16 pc /system/lib/libdvm.so
#17 pc 0000dd40/system/lib/libc.so (__thread_entry+72)
at android.os.FileObserver$ObserverThread.observe(NativeMethod)
at android.os.FileObserver$ObserverThread.run(FileObserver.java:88)
2 Native Backtrace
Backtrace抓取方式
2.1.1添加代码直接抓取
Google默认提供了CallStack
API,请参考
system/core/include/libutils/CallStack.h
system/core/libutils/CallStack.cpp
可快速打印单个线程的backtrace.
2.1.2自动抓取
Natice层的进程发生异常后一般都在/data/tombstones目录下生成文件(墓碑文件),该文件描述了该进程当前的Backtrace,不过是链接地址,需要进行解析。
2.1.3利用debuggerd抓取
MTK已经制作了一个利用debuggerd抓取Native
backtrace的tool
RTT(Runtime Trace),对应的执行命令是:
rtt builttimestamp (Apr 18 :21)
USAGE : rtt[-h] -f function -p pid [-t tid]
-ffuncion : current support functions:
bt (Backtrace function)
-ppid : pid to trace
-ttid : tid to trace
-nname : process name to trace
-h : help menu
2.2解析Native
你可以使用GDB,或者addr2line等tool来解析抓回的Native
Backtrace,从而知道当时正在执行的native代码,
arm-linux-androideabi-addr2line-f -C -e symbols address
公司将addr2line封装后实现了一套解析NativeBacktrace(show
Stack)。参考下文
3 Kernel Backtrace
Backtrace抓取方式
3.1.1运行时抓取
* AEE/RTT工具
* ProcSystem
catproc/pid/task/tid/stack
*Sysrq-trigger
adbshell cat proc/kmsg & kmsg.txt
adbshell &echo 8 & proc/sys/kernel/printk“ //修改printk
adbshell &echo t & /proc/sysrq-trigger“ //打印所有的backtrace
adbshell &echo w & /proc/sysrq-trigger“//打印'-D'
status'D'的process
Longpress volume UP and DOWN more then 10s
Displaystack for process &pid&
bta[DRSTCZEUIMA]
Displaystack all processes
Backtracecurrent process on each cpu
btt&vaddr&
Backtraceprocess given its struct task add
3.1.2添加代码直接抓取
* #include&linux/sched.h&
当前thread:
dump_stack();
其他thread:
show_stack(task,NULL);
3.2Process/Thread状态
&R(running)&,/*0
&S(sleeping)&,/*1
&D(disk sleep)&,/*
&T(stopped)&,/*4
&t(tracing stop)&,/*
&Z(zombie)&,/*16
&X(dead)&,/*32
&x(dead)&,/*64
&K(wakekill)&,/*
&W(waking)&,/*
通常一般的Process处于的状态都是S(sleeping),而如果一旦发现处于如D
(disksleep),T
(stopped),Z
(zombie)等就要认真审查。
系统运行环境
客观的反应系统的执行环境,通常包括如CPU利用率,Memory使用情况,Storage剩余情况等。这些资料也非常重要,比如可以快速的知道,当时是否有Process在疯狂的执行,当时是不是处于严重的low
memory情况,Storage是否有耗尽的情况发生等。
程序执行环境
客观的反应当时某个程序(Kernel也可以看成一个程序)的执行现场,此类资讯通常包括如process的coredump,java
heap prof,kernel的memory
dump等。完整的执行环境,我们可以快速的知道当时具体的变量的值,寄存器值等,可以精细的分析问题。
其他的一些资讯
这些资讯相对来说,比较零散了,如通常的LOG,一些debug命令的结果数据等。
3. 几种典型的异常情况
3.1 Deadlock
下面这个case可以看到PowerManagerService,ActivityManager,WindowManager相互之间发生deadlock。
&PowerManagerService& prio=5tid=25 MONITOR
| group=&main& sCount=1dsCount=0 obj=0x42bae270 self=0x
| sysTid=913 nice=0 sched=0/0cgrp=apps handle=
| state=S schedstat=( 016 ) utm=232 stm=276 core=2
atcom.android.server.am.ActivityManagerService.bindService(ActivityManagerService.java:~14079)
-waiting to lock &0x42aa0f78& (acom.android.server.am.ActivityManagerService) held by tid=16
(ActivityManager)
atandroid.app.ContextImpl.bindServiceCommon(ContextImpl.java:1665)
atandroid.app.ContextImpl.bindService(ContextImpl.java:1648)
atcom.android.server.power.PowerManagerService.bindSmartStandByService(PowerManagerService.java:4090)
atcom.android.server.power.PowerManagerService.handleSmartStandBySettingChangedLocked(PowerManagerService.java:4144)
at com.android.server.power.PowerManagerService.access$5600(PowerManagerService.java:102)
atcom.android.server.power.PowerManagerService$SmartStandBySettingObserver.onChange(PowerManagerService.java:4132)
atandroid.database.ContentObserver$NotificationRunnable.run(ContentObserver.java:181)
atandroid.os.Handler.handleCallback(Handler.java:809)
atandroid.os.Handler.dispatchMessage(Handler.java:102)
atandroid.os.Looper.loop(Looper.java:139)
atandroid.os.HandlerThread.run(HandlerThread.java:58)
&ActivityManager& prio=5tid=16 MONITOR
| group=&main& sCount=1dsCount=0 obj=0x42aa0d08 self=0x
| sysTid=902 nice=-2 sched=0/0cgrp=apps handle=
| state=S schedstat=(
69675 ) utm=1544 stm=2392 core=2
at com.android.server.wm.WindowManagerService.setAppVisibility(WindowManagerService.java:~4783)
-waiting to lock&0x42d17590& (ajava.util.HashMap) held by tid=12 (WindowManager)
atcom.android.server.am.ActivityStack.stopActivityLocked(ActivityStack.java:2432)
at com.android.server.am.ActivityStackSupervisor.activityIdleInternalLocked(ActivityStackSupervisor.java:2103)
atcom.android.server.am.ActivityStackSupervisor$ActivityStackSupervisorHandler.activityIdleInternal(ActivityStackSupervisor.java:2914)
at com.android.server.am.ActivityStackSupervisor$ActivityStackSupervisorHandler.handleMessage(ActivityStackSupervisor.java:2921)
atandroid.os.Handler.dispatchMessage(Handler.java:110)
atandroid.os.Looper.loop(Looper.java:147)
atcom.android.server.am.ActivityManagerService$AThread.run(ActivityManagerService.java:2112)
&WindowManager& prio=5tid=12 MONITOR
| group=&main& sCount=1dsCount=0 obj=0x42a92550 self=0x6491dd48
| sysTid=898 nice=-4 sched=0/0cgrp=apps handle=
| state=S schedstat=(
19755 ) utm=4659 stm=1414 core=1
atcom.android.server.power.PowerManagerService.setScreenBrightnessOverrideFromWindowManagerInternal(PowerManagerService.java:~3207)
-waiting to lock&0x42a95140& (ajava.lang.Object) held by tid=25 (PowerManagerService)
atcom.android.server.power.PowerManagerService.setScreenBrightnessOverrideFromWindowManager(PowerManagerService.java:3196)
atcom.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLockedInner(WindowManagerService.java:9686)
atcom.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLockedLoop(WindowManagerService.java:8923)
atcom.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLocked(WindowManagerService.java:8879)
at com.android.server.wm.WindowManagerService.access$500(WindowManagerService.java:170)
atcom.android.server.wm.WindowManagerService$H.handleMessage(WindowManagerService.java:7795)
atandroid.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:147)
atandroid.os.HandlerThread.run(HandlerThread.java:58)
3.2 执行JNI native code后一直不见返回
&main& prio=5 tid=1 NATIVE
| group=&main& sCount=1dsCount=0 obj=0x41bb3d98 self=0x41ba2878
| sysTid=814 nice=-2 sched=0/0cgrp=apps handle=
| state=D schedstat=(
32612 ) utm=1670 stm=534 core=0
(native backtrace unavailable)
at android.hardware.SystemSensorManager$BaseEventQueue.nativeDisableSensor(NativeMethod)
at android.hardware.SystemSensorManager$BaseEventQueue.disableSensor(SystemSensorManager.java:399)
at android.hardware.SystemSensorManager$BaseEventQueue.removeAllSensors(SystemSensorManager.java:325)
at android.hardware.SystemSensorManager.unregisterListenerImpl(SystemSensorManager.java:194)
at android.hardware.SensorManager.unregisterListener(SensorManager.java:560)
at com.android.internal.policy.impl.WindowOrientationListener.disable(WindowOrientationListener.java:139)
at com.android.internal.policy.impl.PhoneWindowManager.updateOrientationListenerLp(PhoneWindowManager.java:774)
at com.android.internal.policy.impl.PhoneWindowManager.screenTurnedOff(PhoneWindowManager.java:4897)
at com.android.server.power.Notifier.sendGoToSleepBroadcast(Notifier.java:518)
at com.android.server.power.Notifier.sendNextBroadcast(Notifier.java:434)
at com.android.server.power.Notifier.access$500(Notifier.java:63)
at com.android.server.power.Notifier$NotifierHandler.handleMessage(Notifier.java:584)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at com.android.server.ServerThread.initAndLoop(SystemServer.java:1436)
at com.android.server.SystemServer.main(SystemServer.java:1531)
at java.lang.reflect.Method.invokeNative(NativeMethod)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
at dalvik.system.NativeStart.main(NativeMethod)
KERNEL SPACE BACKTRACE, sysTid=814
[&ffffffff&] 0xffffffff from[&c07e5140&] __schedule+0x3fc/0x950
[&c07e4d50&]__schedule+0xc/0x950 from [&c07e57e4&] schedule+0x40/0x80
[&c07e57b0&] schedule+0xc/0x80from [&c07e5ae4&] schedule_preempt_disabled+0x20/0x2c
[&c07e5ad0&]schedule_preempt_disabled+0xc/0x2c from [&c07e3c3c&]mutex_lock_nested+0x1b8/0x560
[&c07e3a90&]mutex_lock_nested+0xc/0x560 from [&c05667d8&] gsensor_operate+0x1bc/0x2c0
[&c0566628&]gsensor_operate+0xc/0x2c0 from [&c0495fa0&] hwmsen_enable+0xa8/0x30c
[&c0495f04&]hwmsen_enable+0xc/0x30c from [&c0496500&]hwmsen_unlocked_ioctl+0x2fc/0x528
[&c0496210&]hwmsen_unlocked_ioctl+0xc/0x528 from [&c018ad98&] do_vfs_ioctl+0x94/0x5bc
[&c018ad10&] do_vfs_ioctl+0xc/0x5bcfrom [&c018b33c&] sys_ioctl+0x7c/0x8c
[&c018b2cc&]sys_ioctl+0xc/0x8c from [&c000e480&] ret_fast_syscall+0x0/0x40
[&ffffffff&] from[&ffffffff&]
4.死机运行环境分析
4.1 系统运行环境
客观的反应系统的执行环境,通常包括如CPU利用率,Memory使用情况,Storage剩余情况等。这些资料也非常重要,比如可以快速的知道,当时是否有Process在疯狂的执行,当时是不是处于严重的low
memory情况,Storage是否有耗尽的情况发生等。
4.2 CPU Usage
追查CPU利用率可大体的知道,当时机器是否有Process在疯狂的运行,当时系统运行是否繁忙。通常死机分析,只需要抓取基本的使用情况即可。下面说一下一般的抓取方式
top可以简单的查询Cpu的基本使用情况
Usage: top[ -m max_procs ] [ -n iterations ] [ -d delay ] [ -s sort_column
] [ -t ] [ -h]
-m num Maximum number of processes to display.
-n num Updates to show before exiting.
-d num Seconds to wait between updates.
-s col Column to sort by (cpu,vss,rss,thr).
-t Show threads instead of processes.
-h Display this help screen.
注意的是top的CPU%是按全部CPU来计算的,如果以单线程来计算,比如当时有开启4个核心,那么最多吃到25%。
个人常见的操作方式如:
top -t -m 5 -n 2
I.E 正常情况
User 2%, System 12%, IOW 0%, IRQ 0%
User 14 + Nice 0 + Sys 67 + Idle 471 + IOW0 + IRQ 0 + SIRQ 2 = 554
PID TID PR CPU%S VSS RSS PCYUIDThread Proc
% R Kroottop top
270 2700 1% S K rootaee_resmon /system/bin/aee_resmon
159 1590 0% D0K 0Kroot bat_thread_kthr
3 3 0 0%S 0K0K root ksoftirqd/0
57 570 0% D0K 0Kroot hps_main
User 1%, System 7%, IOW 0%, IRQ 0%
User 10 + Nice 0 + Sys 41 + Idle 494 + IOW0 + IRQ 0 + SIRQ 0 = 545
PID TID PR CPU%S VSS RSS PCYUIDThread Proc
% R Kroottop top
57 570 0% D0K 0Kroot hps_main
242 4190 0% S Kshell mobile_log_d /system/bin/mobile_log_d
982 9910 0% S Kmedia_rw sdcard/system/bin/sdcard
272 2720 0% S 3Krootem_svr /system/bin/em_svr
从上面可以看出,系统基本运行正常,没有很吃CPU的进程。
I.E 异常情况
User 59%, System 4%, IOW 2%, IRQ 0%
User 1428 + Nice 0 + Sys 110 + Idle 811 +IOW 67 + IRQ 0 + SIRQ 1 = 2417
PID TID PR CPU%S VSS RSS PCYUIDThread Proc
3 14% R492K bg u0_a60Thread-1401 com.android.mms
1 14% R492K bg u0_a60Thread-1400 com.android.mms
2 14% R492K bg u0_a60Thread-1399 com.android.mms
0 14% R492K bg u0_a60Thread-1398 com.android.mms
4 1%R Kshelltop top
User 67%, System 3%, IOW 7%, IRQ 0%
User 1391 + Nice 0 + Sys 75 + Idle 435 +IOW 146 + IRQ 0 + SIRQ 1 = 2048
PID TID PR CPU%S VSS RSS PCYUIDThread Proc
3 16% R492K bg u0_a60Thread-1401 com.android.mms
2 16% R492K bg u0_a60Thread-1399 com.android.mms
0 16% R492K bg u0_a60Thread-1400 com.android.mms
1 16% R492K bg u0_a60Thread-1398 com.android.mms
4 2%R Kshelltop top
可以明显的看到,贵司的mms的4个thread都有进入了deadloop,分别占用了一个cpu
core.同时可以快速抓取他们的java
trace,进一步可以看到当时MMS的四个backtrace,以便快速分析。
&Thread-1401& prio=5 tid=32SUSPENDED JIT
| group=&main& sCount=1dsCount=0 obj=0x self=0x7b183558
| sysTid=32195 nice=0 sched=0/0cgrp=apps/bg_non_interactive handle=
| state=S schedstat=( 8 383002 ) utm=324720 stm=3725 core=5
at com.yulong.android.mms.c.f.d(MmsChatDataServer.java:~1095)
at com.yulong.android.mms.ui.MmsChatActivity$37.run(MmsChatActivity.java:7582)
at java.lang.Thread.run(Thread.java:841)
&Thread-1400& prio=5 tid=31SUSPENDED JIT
| group=&main& sCount=1dsCount=0 obj=0x41f5d8f0 self=0x7be2a8e8
| sysTid=32190 nice=0 sched=0/0cgrp=apps/bg_non_interactive handle=
| state=S schedstat=( 2 382946 ) utm=324805 stm=3685 core=5
at com.yulong.android.mms.ui.MmsChatActivity$37.run(MmsChatActivity.java:~7586)
at java.lang.Thread.run(Thread.java:841)
&Thread-1399& prio=5 tid=30SUSPENDED JIT
| group=&main& sCount=1dsCount=0 obj=0x42564d28 self=0x7b0e6838
| sysTid=32188 nice=0 sched=0/0cgrp=apps/bg_non_interactive handle=
| state=S schedstat=( 6 375959 ) utm=325143 stm=3661 core=7
at com.yulong.android.mms.ui.MmsChatActivity$37.run(MmsChatActivity.java:~7586)
at java.lang.Thread.run(Thread.java:841)
&Thread-1398& prio=5 tid=29SUSPENDED
| group=&main& sCount=1dsCount=0 obj=0x self=0x7be0d128
| sysTid=32187 nice=0 sched=0/0cgrp=apps/bg_non_interactive handle=
| state=S schedstat=( 3 379634 ) utm=325055 stm=3669 core=6
at com.yulong.android.mms.ui.MmsChatActivity$37.run(MmsChatActivity.java:~7586)
at java.lang.Thread.run(Thread.java:841)
当时处于suspend,即意味着当时这四个thread正在执行java
code,而抓取backtrace时强制将thread
suspend。看起来客户改动所致,并且客户有Proguard,麻烦客户自己review代码。
ftrace可以纪录CPU最为详细的执行情况,即linux
scheduler的执行情况。通常默认只开启sched_switch。
如何抓取ftrace可以查询相关的FAQ。
Kernelcore status
有的时候我们需要追查一下,当时Kernel的基本调度情况,以及接收中断的情况,以判断当前CPU执行的基本情况是否异常。比如有时候如果某个中断上来太过频繁,就容易导致系统运行缓慢,甚至死机。
* CPU Sched status
adb shell catproc/sched_debug
Use sysrq-trigger
* CPU interrupts
adb shell catproc/interrupts
adb shell catproc/irq/irq_id/spurious
4.3 Memory Usage
MemoryUsage,我们通常会审查,系统当时memory是否足够,是否处于low
memory状态,是否可能出现因无法申请到memory而卡死的情况。
常见的一些基本信息如下:
* meminfo: basic memory status
adb shell cat proc/meminfo
adb shell cat proc/pid/maps
adb shell cat proc/pid/smaps
* procrank info: all process memory status
adb shell procrank
adb shell procmem pid
adb shell dumpsys meminfo pid
* zoneinfo:
adb shell cat proc/zoneinfo
* buddyinfo:
adb shell cat /proc/buddyinfo
4.4 Storage Usage
查看Storage的情况,通常主要是查询data分区是否已经刷满,sdcard是否已经刷满,剩余的空间是否足够。以及是否有产生超大文件等。
通常使用的命令如df
FilesystemSize Used FreeBlksize
/dev446.0M 128.0K 445.8M 4096
/sys/fs/cgroup446.0M 12.0K 445.9M 4096
/mnt/secure446.0M 0.0K 446.0M 4096
/mnt/asec446.0M 0.0K 446.0M 4096
/mnt/obb446.0M 0.0K 446.0M 4096
/system1.2G 915.3M 355.5M 4096
/data1.1G 136.7M 96
/cache106.2M 48.0K 106.2M 4096
/protect_f4.8M 52.0K 4.8M 4096
/protect_s4.8M 48.0K 4.8M 4096
/mnt/cd-rom1.2M 1.2M 0.0K 2048
/mnt/media_rw/sdcard04.6G 1.1G 3.4G32768
/mnt/secure/asec4.6G 1.1G 3.4G32768
/storage/sdcard04.6G 1.1G 3.4G32768
以及ls, du 等命令,如du
usage: du [-H | -L | -P] [-a | -d depth |-s] [-cgkmrx] [file …]
du -LP -d 1
8 ./lost+found
88 ./local
384 ./misc
48 ./nativebenchmark
912 ./nativetest
8 ./dontpanic
13376./data
8 ./app-private
8 ./app-asec
129424 ./app-lib
136 ./property
116312 ./dalvik-cache
8 ./resource-cache
8 ./mediadrm
8 ./security
3888 ./nvram
8 ./acdapi
88./@btmtk
16 ./media
16 ./agps_supl
8 ./gps_mnl
8 ./nfc_socket
16 ./ccci_cfg
32 ./mdlog
1312 ./system
176 ./recovery
32 ./backup
5.进程运行环境分析
5.1 系统运行环境
当我们怀疑死机问题可能是某个进程出现问题而引发时,通常我们需要对这个进程进行深入的分析,即进程运行环境分析。通常包括分析如,线程状态,各种变量值,寄存器状态等。在Android系统中,我们将其划分成三个层次。
即Java运行环境分析,Native运行环境分析,Kernel运行环境分析。下面分别说明。
5.2 Java运行环境分析
我们对于Zygote
fork出来的process,如APP以及system_server,都会进行Java运行环境分析。其关键是分析Java
Heap,以便快速知道某个Java变量的值,以及Java对象的分布和引用情况。
Heap的分析方式则是抓取Java
Hprof,然后使用MAT等工具进行分析。
*抓取Hprof的手法,如:
第一种方式:使用am命令
adb shell am dumpheap {Process} file
adbshell chmod 777 /data/anr
adbshell am dumpheap com.android.phone /data/anr/phone.hprof
adbpull /data/anr/phone.hprof
第二种方式:使用DDMS命令
在DDMS中选择对应的process,然后在Devices按钮栏中选择Dump
Hprof file,保存即可
第三种方式:通过代码的方式
在android.os.Debug这个class中有定义相关的抓取hprof的method。
public static void dumpHprofData(String fileName) throwsIOE
这样即可在代码中直接将这个process的hprof保存到相对应的文件中,注意这个只能抓取当时的process。
如果想抓其他的process的hprof,那么就必须通过AMS帮忙了。
可以先获取IActivityManager接口,然后调用它的dumpheap方法。具体的代码,大家可以参考
frameworks/base/cmds/am/src/com/android/commands/am/am.java中的调用代码
第四种方式:发送SIGUSER1
在部分机器中,如果具有root权限,可以直接发送SIG
10来抓取,此时对应的Hprof保存在/data/misc下面,文件名如:
heap-dump-tm-pid1882.hprof
首先,DVM的Hprof和标准的Java
Hprof有一些差别,需要使用hprof-conv进行一次转换,将DVM格式的hprof转换成标准的java命令的hprof
hprof-conv in.hprof out.hprof
其次,使用如MAT
Tool,打开转换后的hprof文件,通常我们会
analysisjava thread information
analysisjava var value
analysisObject reference
analysisGC path
具体如何使用MAT分析可以参考MAT的官方网站。
3. Native 运行环境分析
Native运行环境分析,我们通常会采用Core
dump分析手法。Core
dump纪录了当时进程的各类关键资讯,比如变量参数,线程stack,heap,register等。通常可以认为是这个Process当时最为完整的资讯了。但Core
dump往往比较大,有时甚至会超过1G,属于比较重量型的分析手法了。
*如何抓取Core
目前MTK的机器会将Core
Dump转换成AEE
DB。否则对应的Core
dump文件即存放在/data/core目录下
手工抓取时,可以:
adb shell aee -d coreon
adb shell kill -31 PID
dump就可能存放在两个目录下:/data/core,以及/sdcard/mtklog/aee_exp下面新的DB文件。
*如何分析Core
因为通常已经将Core
Dump转换成了AEE
DB。所以首先将AEE
DB解开,即可以看到PROCESS_COREDUMP的文件,有的时候此文件很大,比如超过1G。
而分析Core
Dump的Tools很多,比如traces32,GDB等,这里就不详加说明,可以参考网络上的相关文档。
5.3 Kernel运行环境分析
从82平台上多了ramdump功能,可以发生KE后将82/92的物理内存压缩保存到EMMC的内置卡(默认保存到EMMC内置卡上)(92可以选择外置t卡)上,拿到该文件后就可以转换为kernel
space,查看kernel各种变量,比查看kernel
log更加方便快捷。
只有在eng版本下支持该功能,并且是EMMC的,存在内置T卡才行,
在projectConfig.mk里的MTK_SHARED_SDCARD必须为no即MTK_SHARED_SDCARD=no
连上adb后:
#echo Y& /sys/module/mrdump/parameters/enable
#echo emmc& /sys/module/mrdump/parameters/device (注意82只能在EMMC内置t卡上,不能下这条命令,92可以下这条命令修改到sdcard:#echo
sdcard & /sys/module/mrdump/parameters/device)
这样就开启了ramdump功能,注意重启后无效,必须重新设置才行
之后重新开机,此时会在
内置T卡:/storage/sdcard0/
或外置T卡:/storage/sdcard1/
看到CEDump.kdmp文件,结合kernel/out/vmlinux或out/target/product/$proj/obj/KERNEL_OBJ/vmlinux一起提供给Mediatek即可做进一步kernel异常重启的分析。
6.死机问题场景
当你遇到死机问题时,你可能面临的是下面三种情况。
*有死机现场
资讯最为充足,你可以快速的利用死机现场来分析。
*已经重启过的手机
死机现场已经不复存在,但手机还没有刷机,可以从手机中抓取已经存在的资讯来分析。
*仅仅一些LOG或者其他的资讯
需要从这些LOG或者资讯中猜测当时手机的状态,以及可能死机的原因。
从这三种情况,不难得知,有死机现场的情况下是最容易分析的。而如果仅仅只有一些LOG的话,就需要工程师具有非常丰富的经验,从仅有的LOG中,提取有价值的资讯,来猜测出当时死机的原因。
7.死机问题现场分析
7.1 死机现场分析手法
死机分析如同医生给病人诊断病情,所有的手法不在乎分为两种。
*高科技的诊断设备,分析病人的病情。死机分析就依靠各种技术方法去诊断当时手机的运行的真实状态。
*通过病人的各种活动,分析病人的潜在病因。就依靠各种对手机的操作,以及命令,让手机跑相应的流程,从而进一步分析。
7.2 基本分析流程
下面我们将针对每一个流程进行具体的说明。
7.3 Test Phone Usage
*通过做一些基本的测试,可大体上确认可能引发死机的模块,为后续Debug确定好方向。
*通常只能正向推理,可以做什么=》推断什么模块正常;逆向推理可能因为各种原因而失常。
*Touch Panel
-屏幕是否有响应(一般情况下没响应)。
-如果有响应,可能机器已经活过来了,或者当时把ANR认为了hang机;需要进一步确认情况。
-确认按键的情况,通常都设定振动反馈,如果有,那么就认为当时按键事件可以传递到SystemServer,此时可能System
Server逻辑异常。
*Power Key/ Volumn Up/Down Key
-是否可以亮、灭屏
-可点亮关闭屏幕,说明KPD
-&input manager-&PowerManagerService-&Power-&LCDdriver正常;通常可以怀疑TPD,以及SurfaceFlinger。
*是否可以显示音量调整情况
-可显示音量调整情况,进一步说明SurfaceFlinger也正常,进一步怀疑TPD,或者直接的APP无响应的情况。
*SystemUI & Status Bar
- Status Bar是否可以拉下,以便防止只是活动区卡住的情况,可下拉,说明只是APP卡住,或者lockscreen无法解锁的情况
*LockScreen
-测试LockScreen是否可以解锁,
* Home Key/ Back Key/Menu Key
-确认当时是否只是APP
hang住的情况,避免将ANR误判为死机
*插入USB观察充电情况
-可确认Surfaceflinger,System
Server的运行情况
7.4 USB/ADB Debug Hang
7.4.1 USB/ADB Debug准备
*插入USB,确认ADB是否可以使用
-首先查看的设备管理器里面是否出现对应的设备
-在命令行中输入adb
devices,看是否可以打印设备信息,在输入之前您最好先输入adb
kill-server保证pc上的adb
client没有卡住
-请确保您使用的PC上已经安装ADB,USB端口本身正常
7.4.2 USB/ADB连接分析
*Case1: adb能正常连接,adb
- adb目前可以正常接入,可以进行USB/ADB
*Case2: windows设备管理器有反应,adb
shell提示device
not found。
-确认adb驱动是否安装好,USB的uid和vid是否和driver匹配。
-可能机器的adbd已经无法对接,尝试adbkill-server来确认
*Case3: windows设备管理器有反应,adb
shell提示offline。
-机器的adbd拒绝连接,或者adbd无法拉起。
- PC adb版本过低
-很可能adbd已经卡住,adbdprocess
status为‘D’
7.4.3机器状态基本检测
* ps or ps-t or ps -t -p查看进程基本状态
-t以线程为单位打印
-p附加打印线程优先级信息
**追查如system
server,surfaceflinger,service
manager,media
server(ss,sf,sm、ms),zygote,等关键进程的状态,进行初步确认。正常情况下,都应处于’S’,异常情况有如’D’,‘T’,‘Z’,‘R’等
**大体追查ss,sf,sm,ms,zygote等的memory情况,是否有明显的溢出情况
**大体查看当时的ss
pid,如果机器上层没有重启过,通常sf
pid & 200,ss
pid & 600,如果pid比较大就说明上层重启过。
**是否还存在特别进程,如ipod,表示在ipo关机中,如aee_core_forworder,表示在抓core
dump,aee_dumpstate表示aee在抓取db信息等。
**追查debuggerd的process数量,通常正常时,只有一个debuggerd
process,pid
& 200,如果有达到4个debuggerd,这个时候将无法进行rtt之类的操作
-审查storage的使用情况,查看SD卡和data分区使用情况,特别是如SD卡已满,或者data分区写满等。
* catproc/meminfo,procrank
-审查当前的memory使用情况,追查各个进程的memory情况
-审查当前system
properties情况
* top-t -m 5 -n 2
-摸一摸手机,感觉有点热,或者发烫的话,说明通常是CPU利用率比较高
-大体上审查当前CPU的利用情况,不求精湛
总之,机器状态基本检测,目标就是通过简单几个命令直接侦测当前手机最为可能的异常情况。包括关键进程基本状态,CPU利用率,memory状况,storage状况等。做出基本的预先分析,从而为下一步的debug打好基础。
7.5 UART Debug
当usb/adb无法确认问题时或者已经无法连接时,我们需要利用UART/KDB来进一步厘清问题。
确认UART以及UART
Console已经开启。
ENG版本默认开启,User版本默认关闭。通常在User版本上如果需要抓取UART日志的话需要用散件工具单烧ENG版本的LK分区重启就可以抓取UART日志了。
目前我司一般的UART端口都不支持输入,所以只能通过输出的UART输出的log来分析问题。
7.6 确认死机的模块
我们又回到了最开始的可能会导致死机的模块,下面我们将针对每一个模块做详细的说明。
Input Driver-Input System
*确认Input
Driver-Input System通路是否正常,即inputdriver是否可以传上正常的输入
*最常见的检测方式是adb
shell getevent
如直接输入adb
shell getevent可以看到:
D:\log&adbshell getevent
add device1: /dev/input/event0
name: &mtk-kpd&
could notget driver version for /dev/input/mouse0,Not
atypewriter
add device2: /dev/input/event3
name: &mtk-tpd&
add device3: /dev/input/event2
name: &hwmdata&
add device4: /dev/input/event1
name: &ACCDET&
could notget driver version for /dev/input/mice,Not
atypewriter
对应的操作命令是:
Usage:getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l]
[-q][-c count] [-r] [device]
-t: show time stamps
-n: don't print newlines
-s: print switch states for given bits
-S: print all switch states
-v: verbosity mask (errs=1,dev=2,name=4,info=8,vers=16,pos.
events=32,props=64)
-d: show HID descriptor,if
-p: show possible events (errs,dev,name,pos.
-i: show all device info and possible events
-l: label event types and names in plain text
-q: quiet (clear verbosity mask)
-c: print given number of events then exit
-r: print rate events are received
通常我们会一项一项的确认native层是否可以收到Kernel传递来的input
event事件。
比如我们追查KPD是否有效果,按power
key可以看到相关的行为。
D:\log &adbshell getevent -t -l /dev/input/event0
[.433356]EV_KEY KEY_POWERDOWN
[.433356]EV_SYNSYN_REPORT
[.527596]EV_KEYKEY_POWER UP
[.527596]EV_SYNSYN_REPORT
[.824871]EV_KEYKEY_POWERDOWN
[.824871]EV_SYNSYN_REPORT
[.996095]EV_KEYKEY_POWER UP
[.996095]EV_SYNSYN_REPORT
[.495346]EV_KEYKEY_POWERDOWN
[.495346]EV_SYNSYN_REPORT
[.530963]EV_KEYKEY_POWER UP
[.530963]EV_SYNSYN_REPORT
当然如果屏幕是点亮时,肯定就要快速追查tpd以及模拟按键是否正常
D:\log &adbshell getevent -t -l /dev/input/event5
[.432516]EV_ABS ABS_MT_TOUCH_MAJOR
[.432516]EV_ABS ABS_MT_TRACKING_ID
[.432516]EV_KEYBTN_TOUCHDOWN
[.432516]EV_ABS ABS_MT_POSITION_X
[.432516]EV_ABS ABS_MT_POSITION_Y
[.432516]EV_SYNSYN_MT_REPORT
[.432516]EV_SYNSYN_REPORT
[.496797]EV_ABS ABS_MT_TOUCH_MAJOR
[.496797]EV_ABS ABS_MT_TRACKING_ID
[.496797]EV_ABS ABS_MT_POSITION_X
[.496797]EV_ABS ABS_MT_POSITION_Y0000027d
[.496797]EV_SYNSYN_MT_REPORT
[.496797]EV_SYNSYN_REPORT
[.506985]EV_ABS ABS_MT_TOUCH_MAJOR
[.506985]EV_ABS ABS_MT_TRACKING_ID
[.506985]EV_ABS ABS_MT_POSITION_X
[.506985]EV_ABS ABS_MT_POSITION_Y0000027a
[.506985]EV_SYNSYN_MT_REPORT
[.506985]EV_SYNSYN_REPORT
[.517713]EV_KEYBTN_TOUCH UP
[.517713] EV_SYNSYN_MT_REPORT
[.517713]EV_SYNSYN_REPORT
如果发现无法收到此类资讯,那么就可以确认对应的devices可能有故障,需要请对应的driver&
vendor工程师来分析。
system-server logic
此分析的关键在于分析system-server是否还在正常的运转,这是非常重要的,据统计,40%的usb可以debug的hang机问题,都可以通过对system-server逻辑的审查找出原因。
Systemserver是整个android上层的中枢,容纳了最为重要的service。
server的分析主要是通过java
native的backtrace来追查Systemserver的关键thread有没有被lock/dead
lock,有没有进入dead
loop,状态是否正常。
从死机机的角度来看system
server关键的thread如:
Serverthread:
System-server的main
looper建立在serverthread上,所有service如果不单独创立thread-looper那么都将运行在这个Server
thread上,其关键性不言而喻,用watchdog来监测该thread。
ActivityManager:
处理所有的Activity状态切换,broadcast,以及ANR监测等等,非常重要。
WindowManager:
处理各种window叠加与切换,Input相关处理。
WindowManagerPolicy/UI:
主要处理LockScreen相关流程,它卡住,lockscreen无法解锁
PowerManagerService:
处理Power相关事宜,它卡住,屏幕无法熄灭,点亮
InputDispatcher/InputReader
System相关事宜,一旦他们卡住,那么所有的Input
Event都无法反馈到其他的module,机器死机就成必然。
在KK以及KK以后的版本中Google取消了serverthread这样的main
looper thread,直接使用system
server的第一个thread作为main
looper。Google对system
server的threads做了进一步的整合,以减少繁杂的线程数,新增了如android.io,android.ui,android.fg,android.bg等threads。将大量的普通型的Handler按时效分类分散到上面的4个threads中。
所以KK及更高的版本还需要分析ndroid.io,android.ui,android.fg,android.bg等thread。
这些thread都通过执行MQ-Looper-Handler的模式运行,所以正常的时候的java/native
backtrace都是:
at android.os.MessageQueue.nativePollOnce(NativeMethod)
at android.os.MessageQueue.next(MessageQueue.java:138)
at android.os.Looper.loop(Looper.java:150)
#00 pc 0002599c/system/lib/libc.so (epoll_wait+12)
#01 pc /system/lib/libutils.so (android::Looper::pollInner(int)+94)
#02 pc /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+92)
#03 pc 0006ca5d/system/lib/libandroid_runtime.so(android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22)
一旦不是就可能已经出现异常了。
BinderThread
Systemserver为外界提供服务,绝大多数都通过binder与其他process对接。BinderThread的数量动态调整,默认不会超过16个,如果数量达到16个,即说明当前system
server可能非常繁忙,有process非常频繁的和Process通信。
在JB以及以前版本,System-server的第一个thread,在调起serverthread后,自己加到IPCthread
pool中,成为Binder
Thread的一员。
对于Binder
Thread,正常时对应的Backtrace:
/system/lib/libc.so(__ioctl+8)
/system/lib/libc.so (ioctl+28)
/system/lib/libbinder.so(android::IPCThreadState::talkWithDriver(bool)+140)
#03 pc 0001dae3 /system/lib/libbinder.so(android::IPCThreadState::getAndExecuteCommand()+6)
#04 pc 0001db79 /system/lib/libbinder.so(android::IPCThreadState::joinThreadPool(bool)+48)
#05 pc 00021a79 /system/lib/libbinder.so
#06 pc 0000ea01 /system/lib/libutils.so(android::Thread::_threadLoop(void*)+216)
#07 pc /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+68)
/system/lib/libutils.so
/system/lib/libc.so(__thread_entry+72)
at dalvik.system.NativeStart.run(Native Method)
抓取system
server的java
backtrace,依次check
serverthread(JB),ActivityManager,WindowManager,WindowManagerPolicy,PowerManagerService以及android.io,android.bg,android.fg,android.ui的状态,如状态异常,则依次推导。
当发现java
backtrace最后调用到异常nativemethod时,抓取其native
backtace,通过native
backtrace进一步追查.
如果在native
backtrace中,发现已经调入binderdriver,那就是通过binder进行IPC
call,这个时候就要知道binder的对端process,然后查阅它的binder
thread进程进一步分析问题。
Case1: Abnormal Java Backtrace “Deadlock”
图片deadlock-java-backtrace.png
Case2: Abnormal Java Backtrace “Lock in native thread&
图片lock-in-native-thread.png
Case3: Abnormal native Backtrace “Lock in Binder”
图片lock-in-binder.png
Case4: Abnormal native Backtrace &Lock in Binder thread&
图片lock-in-binder-thread.png
当确认前面的key
thread都没用问题,而通过getevent确认event已经传递到system
server。问题可能出在inputsystem中。
WindowManagerService通过InputManager提供的接口开启一个线程驱动InputReader不断地从/dev/input
/目录下面的设备文件读取事件,然后通过InputDispatcher分发给连接到WindowManagerService服务的客户端。
Reader正常的backtrace:
&InputReader& sysTid=611
/system/lib/libc.so(epoll_wait+12)
/system/lib/libinput.so(android::EventHub::getEvents(int, android::RawEvent*, unsigned int)+1092)
#02 pc 0002aaf7 /system/lib/libinput.so(android::InputReader::loopOnce()+142)
/system/lib/libinput.so(android::InputReaderThread::threadLoop()+8)
/system/lib/libutils.so(android::Thread::_threadLoop(void*)+492)
#05 pc 0004d12b/system/lib/libandroid_runtime.so(android::AndroidRuntime::javaThreadShell(void*)+150)
/system/lib/libutils.so
#07 pc 0000f66c /system/lib/libc.so (__thread_entry+80)
Dispatcher正常的backtrace:
&InputDispatcher& sysTid=610
/system/lib/libc.so(epoll_wait+12)
#01 pc 0001c05c /system/lib/libutils.so(android::Looper::pollInner(int)+140)
/system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+76)
/system/lib/libinput.so(android::InputDispatcher::dispatchOnce()+94)
#04 pc 0001f5bd /system/lib/libinput.so(android::InputDispatcherThread::threadLoop()+8)
/system/lib/libutils.so(android::Thread::_threadLoop(void*)+492)
#06 pc 0004d12b/system/lib/libandroid_runtime.so(android::AndroidRuntime::javaThreadShell(void*)+150)
/system/lib/libutils.so
#08 pc 0000f66c /system/lib/libc.so(__thread_entry+80)
Backtrace通常都可以精确的定位问题点,比如卡在了哪一行。
那有没有可能您抓backtrace时,恰好运行到,造成乌龙的情况呢?这个通常需要具体情况具体分析
--- NativeBacktrace处于R状态
--- JavaBacktrace处于Suspend状态,Running状态
---Backtrace处于明确的非block状态
--- DoubleBacktrace确认是否CPU有运转
随着android版本的推进,system-server越来越显得庞大,为此Google对system-server做了分拆动作.
After 4.0SurfaceFlinger removed from system-server and created by init,single
process SurfaceFlinger。
除SurfaceFlinger外,对system-server影响最大的是MediaServer。
注意对于surfaceflinger,mediaserver等非DVM
Process,切忌不要对他们send
signalSIGQUIT(3),将导致对应的process直接退出
Display logic
DisplayControl Flow
display-control-flow.png
*Surface Manager(Surfaceflinger)
**Surfaceflinger是用户空间中Framework下libraries中负责显示相关的一个模块
**当系统同时执行多个应用程序时,Surfaceflinger负责管理显示,主要包括显示的叠加和显示的渲染
**其中显示的叠加,MTK架构按照一定的原则和算法,主要用到GPU和OVL模块的overlay功能来做2D/3D绘图的显示合成
OVL硬件做HW
Overlay功能
* GPU(Graphic Processing Unit )
**aspecialized electronic circuit designed to accelerate the image processing,frame
buffer rendering for output to a display。
*FrameBuffer
**基于Linux
Frame buffer模型的MTKFramebuffer实作,主要来管理frame
*DDP(DisplayData Path)
** MTKDisplay Hardware Controller,包括OVL,DMA,Color
Processor,BLS,
DSI/DBI/DPIController
DisplayData Flow
display-data-flow.jpg
* Display大致的流程说明
** APP(包括WMS)会把数据透过Surface送到SF(surfaceflinger)
** SF按照一定规则,通过GPU/HWC把多个Surface合成,并设定到DDP
OVL的对应layer
*** MTK OVL一般有4
layer(可能不同平台会有差异,目前基本都是4
layer),每个layer都可以设定一个对应的图层,然后OVL把这写图层合成后送给DDP的下一级Module
***某些情况下(比如总的图层超过4个,OVL无法处理等各种case),会使用GPU去做2D/3D的图层合成到frame
** SF/HWC最后把GPU合成图层以及需要OVL合成的图层,设定到OVL的HW
Register,并trigger
** MTK DDP就会把合成的数据像管道一样流向LCM
module,最后Panel显示相关的画面
对Display的快速分析,我们主要是两个手段,第一个确认FrameBuffer数据是否和理想数据一致,第二个确认SurfaceFlinger状态是否正确。
*确认FrameBuffer数据和理想数据一致,那么说明android上层的处理行为都是正常的,而问题就很可能出在LCM的driver或者LCM本身问题,此时需要联系LCM的driver工程师以及LCM
vendor来确认分析,这里不再详细说明。
*确认SurfaceFlinger的状态,用于审查SurfaceFlinger的行为是否正常,对应的Thread是否能够正常工作,我司已经在SurfaceFlinger里面导入了Watchdog机制,审查SurfaceFlinger是否有卡住的情况,对应在main
log里面会打印如:
[SF-WD]detect SF maybe hang!!!
这样的LOG,并且会纪录卡顿的时机,如果持续卡顿,毫无疑问,SurfaceFlinger已经卡住,此时就要分析对应的backtrace以及LOG。
*SurfaceFlinger的线程情况在不同的版本上变化比较大,最直接的方式是审查它binder
thread情况,以及Event
Loop的执行情况。binderthread和system
server情况一致,不再详细说明。Event
Loop在JB以及,JB以及KK上都不相同,这里分别说明。
在JB以前的版本,SurfaceFlinger的Event
Loop使用的是普通的pthread控制,并且SurfaceFlinger的第一个Thread在执行SurfaceFlinger的初始化后,转换为了binder
thread。而Event
Loop的thread是新起的&SurfaceFlinger&
thread。对应的正常backtrace是:
surfaceflinger-event-loop-beforce-jb.png
在JB版本,SurfaceFlinger的Event
Loop换成了Message
Queue-Looper,对应的backtrace是:
surfaceflinger-event-loop-jb.png
在KK版本,SurfaceFlinger的第一个thread直接作为了Event
Loop thread,对应的backtrace是:
surfaceflinger-event-loop-kk.png
然后再根据SurfaceFlinger的代码逻辑,以及backtrace的lock情况进行审查分析。
8.无现场猜测分析
8.1 无场景猜测与分析
前面已经提到,无场景分成两类
*已经重启过的手机
死机现场已经不复存在,但手机还没有刷机,可以从手机中抓取已经存在的资讯来分析。
*仅仅一些LOG或者其他的资讯
需要从这些LOG或者资讯中猜测,当时手机的状态,以及可能死机的原因。
对于前者,如同法医解剖逝者遗体,分析可能的死亡原因。而对于后者,就相当于警察叔叔对一些曾年旧案的考证,挖掘与分析,难度可想而知。
8.2 死机资讯的完整纪录
为了能够更好更快的分析死机问题,通常我们都强烈建议保存好现场,如果一些特殊环境下无法保存现场,那么就要求测试工程师详细的纪录当时现场环境,包括但不限于下面的资讯:
*发现死机的时间
---如果是发现时,感觉机器早已经死机,也请说明
---如有截图,拍照,可以从图像上先获取
*复现手法,操作的流程,当时环境
---强调在正常使用到死机过程中的操作。
---环境状态通常包括温度,湿度,网络信号状况。
---复现流程的视频
*复现手机情况
---复现的软件版本:版本号?
---外部设备情况:有插入SD卡?耳机?SIM?
---软件开启情况:开启蓝牙?WIFI?数据服务?GPS?
*复现的概率
---多少台手机做过测试,多少台手机可以复现。
---前后多少个版本可以复现,从哪个版本开始可以复现。
其中死机的时间点至关重要,需要现场的工程师一定要比较精确的纪录。
8.3 死机Log分析
*确认hang机时间,和当时是否已经死机至关重要
*如果当时kernel已经异常,mobile
log无法抓取log,那么log的价值大打折扣。
*反过来如果当时mobile
log还在继续,说明至少kernel整体功能正常,先分析android上层的情况。
*从LOG中分析SystemServer,Surfaceflinger行为是否正常,是否有Lock住。
*查看System
Server中关键Service执行情况,如AMS,WMS,PowerManagerService,WindowManagerPolicy。
*观测AMS是比较快速的方法,因为AMS工作时,会使用到很多其他Service的Lock,比如broadcast,start
activity,start
service。通常一旦system
server有卡住,则AMS也会卡住,反过来如果AMS没有卡住,那么通常就意味着systemserver没有直接卡住。
*查看Surfaceflinger,先查sf-wd,看看是否surfaceflinger是否已经卡住,然后再追查fps情况,HWComposer等情况。
*查看Power
Key行为来确认上下通路是否正常,一般人看到死机,通常会去按一下Power
Key来确认是否死机。
*查看Binder信息,看看Systemserver,Surfaceflinger等的IPC情况。
因为死机,一般人都会习惯性的按Power
key来查看是否可以恢复,而按Power
Key的处理流程,涉及从Kernel
=& Input System =& System Server =& SurfaceFlinger等的整个流程,我们可以观察这个流程来查看hang机情况。
* KPDreceives Interrupt and generate Power Key
power-key-1。png
* Systemserver receives Key and call set_screen_state
power-key-2。png
* PowerState Update: request_suspend_state
power-key-3.png
* Setscreen on: mt65xx_leds_set_cust
power-key-4.png
通过审查每一个阶段流程,确认可能的hang机点。注意的是不同的版本可能有所不同,可以先用正常的机器复现一次后比对。
8.4死机Log 分析, trace 辅助
*如果有提供/data/anr下的trace,或者相关的db文件。在确认死机的时间下,check
trace对应的时间点,如果时间在死机或者hang机后,则是一份非常有价值的trace。通常查“-----”or“pid”
*借机审查system
server,surfaceflinger的状况。
*如果/data/anr下有标准full_traces_xx即标柱这个backtrace是SWT产生的宝贵backtrace,里面一定有system
server等的backtrace。
9.死机日志抓取
通常情况下,依靠Log可以找到对应的异常模块,但无法找出根本原因。需要依赖更多的信息来debug确认,所以针对这种情况,我们需要让测试人员抓出更多的信息来分析。
9.1 当机器死机时,建议使用下面脚本抓取资讯:
@echo &Pull important informationfrom hang phone, written by Yanghui Li&
adb devices
@echo &attach sdcard/mtklog&
adb pull /sdcard/mtklog mtklog/
@echo “attach sdcard2/mtklog”
adb pull /sdcard2/mtklog mtklog/sdcard2
@echo &attach trace&
adb pull /data/anr mtklog/anr
@echo &attach rtt dump forsurfaceflinger&
adb pull /data/rtt_dump*mtklog/sf_dump
adb pull /data/anr/sf_rtt mtklog/sf_rtt_1
@echo &attach data aee db&
adb pull /data/aee_exp mtklog/data_aee_exp
@echo &attach data mobilelog&
adb pull /data/mobilelogmtklog/data_mobilelog
@echo &attach NE core&
adb pull /data/core mtklog/data_core
@echo &attach tombstones&
adb pull /data/tombstonesmtklog/tombstones
@echo “attach phone state”
adb shell ps -t& mtklog/ps.txt
adb shell top -t -m 5 -n 3 & mtklog/top.txt
adb shell service list &mtklog/serviceList.txt
adb shell cat /proc/meminfo &mtklog/meminfo
adb shell cat /proc/buddyinfo &mtklog/buddyinfo
adb shell procrank & mtklog/procrank.txt
adb shell cat proc/sched_debug &mtklog/sched_debug.txt
adb shell cat proc/interrupts &mtklog/interrupts.txt
adb shell dumpstate & mtklog/dumpstate.txt
@echo &finish.&
9.2 当机器重启后,可以使用下面脚本抓取:
adb devices
@echo&抓出sdcard/mtklog&
adb pull/sdcard/mtklog mtklog/
@echo&抓出trace&
adb pull/data/anr mtklog/anr
@echo&抓出data
adb pull/data/aee_exp mtklog/data_aee_exp
@echo&抓出data
mobilelog&
adb pull/data/mobilelog mtklog/data_mobilelog
@echo&抓出NE
adb pull/data/core mtklog/data_core
@echo&抓出tombstones&
adb pull/data/tombstones mtklog/tombstones
@echo&抓sf
adb pull/data/rtt_dump* mtklog/sf_rtt
adb pull/data/anr/sf_rtt mtklog/sf_rtt_1
@echo&完成&
应当说针对不同的场景,死机和重启意义不一样。
对于普通用户来说,死机的危害性和重要性远大于重启。死机意味着机器在很长一段时间内机器都运行不正常,不能使用。危害性仅次于不能开机。重启很多时候用户都无法感知到,除非当时正在操作手机,并且通常很快就可以恢复。所以在USER版本中,我们要尽可能的把死机转换成重启。
对于开发者来说,重要的是解决问题,通常把死机转换成重启,为了规避一些未知因素,通常抓取的资讯比较少,难以直接分析问题。而如果有死机的现场,分析起来就相对容易得多。
所以针对ENG版本,我们建议不要把死机转换成重启。针对USER版本,尽可能的把死机转换成重启。
10.2 死机如何转换成重启
死机转换成重启的通用手段就是Watchdog机制,通过watchdog监测系统执行情况,一旦发生watchdog
timeout,则做相应的异常处理。通常对于严重的情况,就是重启系统。
在android中有两个最为重要的Watchdog机制,一个是System
Server内部的Watchdog,用于监测System
Server重要Thread是否正常,关键Lock是否可以快速获取。一旦出现故障,则快速重启android上层。另外一个就是整个系统的Watchdog,这个依赖于不同平台厂商的实现,对于MTK平台来说,大体的做法是每一个cpu
core对应一个Watchdog
Thread [wdtk-X],周期性(20s)的去写RGUregister,而RGUregister的timeout时间是30s,即如果出现一个core的watchdog
thread没有按时踢狗,那么就会触发一个timeout的FIQ,产生一个KE引发系统完整重启。
MTK在KK以后的平台,又做了hangmonitor机制,system
server的watchdog
thread周期性的踢kernel中的一个计时器,并设定下一次踢狗的时间,如果在设定的时间内没有踢狗,即意味着system
server的watchdog本身可能卡住,那么hang
monitor机制就会自己触发一个HWT,引发系统完整重启。
当然并非所有的死机问题都能转换成重启。
10.3 死机VS重启
HWHang[maybe]
IRQ Disable & run longtime [After ICS Reboot, GB Hang]
SoftIRQ run longtime[Reboot]
Preempt Disable longtime [Reboot]
RT Thread busy[RT &99] [Hang or Hanglong time then reboot]
Kernel ModuleHang[maybe]
---- Not block watchdog thread reboot.
Native ModuleHang[maybe]
---- Not block watchdog thread reboot.
SurfaceFlingerHang[GB reboot, ICS/JB Hang, KK Hang long time then reboot]
Display subsystemHang [Hang]
LCMHang[Hang]
Input DriverFail[Hang]
Input SystemHang[GB, ICS Hang and JB, KK Reboot]
WindowManagerPolicyHang [Maybe]
---- Need check the serverthread state
System serverdeadlock[Reboot]
System server logicabnormal [Maybe]
Surfaceflinger logic abnormal[Maybe]
转载自:/blog/jinlu7611/article/p-5005930.html
以上就是Android的死机、重启问题分析方法的全文介绍,希望对您学习Android应用开发有所帮助.
这些内容可能对你也有帮助
更多可查看Android开发列表页。
猜您也会喜欢这些文章

我要回帖

更多关于 project 2013 的文章

 

随机推荐