Android 信号处理面面观 之 信号定义、行为和来源
总结:
Android中:
Sending signal. PID: XXX SIG: 3 ====>打印trace
原文:http://blog.csdn.net/rambo2188/article/details/6998349
传统 Unix系统的信号定义和行为
所有的符合Unix规范(如POSIX)的系统都统一定义了SIGNAL的数量、含义和行为。 作为Linux系统,Android自然不会更改SIGNAL的定义。在Android代码中,signal的定义一般在 signum.h (prebuilt/linux-x86/toolchain/i686-linux-glibc2.7-4.4.3/sysroot/usr/include/bits/signum.h)中:
/* Signals. */
#define SIGHUP 1 /* Hangup (POSIX). */
#define SIGINT 2 /* Interrupt (ANSI). */
#define SIGQUIT 3 /* Quit (POSIX). */
#define SIGILL 4 /* Illegal instruction (ANSI). */
#define SIGTRAP 5 /* Trace trap (POSIX). */
#define SIGABRT 6 /* Abort (ANSI). */
#define SIGIOT 6 /* IOT trap (4.2 BSD). */
#define SIGBUS 7 /* BUS error (4.2 BSD). */
#define SIGFPE 8 /* Floating-point exception (ANSI). */
#define SIGKILL 9 /* Kill, unblockable (POSIX). */
#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */
#define SIGSEGV 11 /* Segmentation violation (ANSI). */
#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */
#define SIGPIPE 13 /* Broken pipe (POSIX). */
#define SIGALRM 14 /* Alarm clock (POSIX). */
#define SIGTERM 15 /* Termination (ANSI). */
#define SIGSTKFLT 16 /* Stack fault. */
#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */
#define SIGCHLD 17 /* Child status has changed (POSIX). */
#define SIGCONT 18 /* Continue (POSIX). */
#define SIGSTOP 19 /* Stop, unblockable (POSIX). */
#define SIGTSTP 20 /* Keyboard stop (POSIX). */
#define SIGTTIN 21 /* Background read from tty (POSIX). */
#define SIGTTOU 22 /* Background write to tty (POSIX). */
#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */
#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */
#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */
#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */
#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */
#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */
#define SIGPOLL SIGIO /* Pollable event occurred (System V). */
#define SIGIO 29 /* I/O now possible (4.2 BSD). */
#define SIGPWR 30 /* Power failure restart (System V). */
#define SIGSYS 31 /* Bad system call. */
#define SIGUNUSED 31
我们知道,信号处理的方式一般有三种:
1. 忽略 接收到信号后不做任何反应。
2. 自定义 用自定义的信号处理函数来执行特定的动作
3. 默认 接收到信号后按默认得行为处理该信号。 这是多数应用采取的处理方式。
而 传统 UNIX系统对以上信号的默认处理如下图所示 (来自 APUT ):
Android 系统 信号处理的行为
我们知道,信号处理的行为是以进程级的。就是说不同的进程可以分别设置不同的信号处理方式而互不干扰。同一进程中的不同线程虽然可以设置不同的信号屏蔽字,但是却共享相同的信号处理方式 (也就是说 在一个线程里改变信号处理方式,将作用于该进程中的所有线程)。
Android也是Linux系统。所以其信号处理方式不会有本质的改变。但是为了开发和调试的需要,android对一些信号的处理定义了额外的行为。 下面是这些典型的信号在Android系统上的行为:
1. SIGQUIT ( 整型值为 3)
上面的表10-1显示,传统UNIX系统应用,对SIGQUIT信号的默认行为是 "终止 + CORE"。也就是产生core dump文件后,立即终于运行。
Android Dalvik应用收到该信号后,会 打印改应用中所有线程的当前状态,并且并不是强制退出。这些状态通常保存在一个特定的叫做trace的文件中。一般的路径是/data/anr/trace.txt. 下面是一个典型的trace文件的内容:
----- pid at -- :: -----
Cmd line: com.android.phone DALVIK THREADS:
(mutexes: tll= tsl= tscl= ghl= hwl= hwll=)
"main" prio= tid= NATIVE
| group="main" sCount= dsCount= obj=0x400246a0 self=0x12770
| sysTid= nice= sched=/ cgrp=default handle=-
| schedstat=( ) utm= stm= core=
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:)
at android.os.Looper.loop(Looper.java:)
at android.app.ActivityThread.main(ActivityThread.java:)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:)
at dalvik.system.NativeStart.main(Native Method) "Thread-29" prio= tid= WAIT
| group="main" sCount= dsCount= obj=0x406f0d50 self=0x208c18
| sysTid= nice= sched=/ cgrp=default handle=
| schedstat=( ) utm= stm= core=
at java.lang.Object.wait(Native Method)
- waiting on <0x406f0d50> (a com.motorola.android.telephony.cdma.OemCdmaTelephonyManager$Watchdog)
at java.lang.Object.wait(Object.java:)
at com.motorola.android.telephony.cdma.OemCdmaTelephonyManager$Watchdog.run(OemCdmaTelephonyManager.java:) "FileObserver" prio= tid= NATIVE
| group="main" sCount= dsCount= obj=0x4068b2f8 self=0x1ed278
| sysTid= nice= sched=/ cgrp=default handle=
| schedstat=( ) utm= stm= core=
at android.os.FileObserver$ObserverThread.observe(Native Method)
at android.os.FileObserver$ObserverThread.run(FileObserver.java:) "android.hardware.SensorManager$SensorThread" prio= tid= NATIVE
| group="main" sCount= dsCount= obj=0x406bbd90 self=0x1b2ec0
| sysTid= nice=- sched=/ cgrp=default handle=
| schedstat=( ) utm= stm= core=
at android.hardware.SensorManager.sensors_data_poll(Native Method)
at android.hardware.SensorManager$SensorThread$SensorThreadRunnable.run(SensorManager.java:)
at java.lang.Thread.run(Thread.java:)
...
该文件包好很多重要的信息,可以说明在发生异常是,当前进程的状态 (后面有单独的一篇文章分析改文件)
2. 对于很多其他的异常信号 (SIGILL, SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGSTKFLT ), Android进程 在退出前,会生成 tombstone文件。记录该进程退出前的轨迹。一个典型的tombstone文件内容如下:
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'verizon/pasteur/pasteur:3.2.2/1.6.0_241/eng.drmn68.20111115.094123:eng/test-keys'
pid: , tid: >>> /system/bin/mediaserver <<<
signal (SIGFPE), code (?), fault addr 000000b5
r0 r1 r2 ffffffff r3
r4 r5 r6 000000a5 r7
r8 662f9c00 r9 662f9c00 fp
ip aff17699 sp 4057f9dc lr aff176a7 pc aff0c684 cpsr
d0 6f762f6f69647502 d1
d2 d3 400120dc00000000
d4 d5
d6 3ce449db86666666 d7 3e4ccccd3e4ccccd
d8 000000000035c6a8 d9 000000000035c6a8
d10 d11
d12 d13
d14 d15
d16 d17 3e582f8f86b6a000
d18 3fe0000000000000 d19 3fe000000c17c7c3
d20 3f11504c292739d4 d21 bebbb371092382c4
d22 3ff0000000000000 d23 3ff43d135cda918c
d24 3e66376972bea4d0 d25
d26 d27
d28 d29
d30 d31
scr # pc 0000c684 /system/lib/libc.so (kill)
# pc 000176a4 /system/lib/libc.so (raise) libc base address: aff00000 code around pc:
aff0c664 e2601000 e0100001 116f0f10
aff0c674 e12fff1e e92d50f0 e3a07025 ef000000
aff0c684 e8bd50f0 e1b00000 512fff1e ea00ade7
aff0c694 e92d50f0 e3a070ee ef000000 e8bd50f0
aff0c6a4 e1b00000 512fff1e ea00ade0 f5d0f000 code around lr:
aff17684 00029e2e 461cb537 e9cd17dd f7f34500
aff17694 bd3eef02 4604b510 ed5ef7f3 f7f44621
aff176a4 bd10efea 2300b510 f7f44802
aff176b4 bd10edf6 fee1dead 2400b513
aff176c4 ec9cf7f4 bf00bd1c 4c11b570 stack:
4057f99c a2b6fd15 /system/lib/libstagefright.so
4057f9a0
4057f9a4 a2b6fe51 /system/lib/libstagefright.so
4057f9a8 000fb02c
4057f9ac a2b6fde7 /system/lib/libstagefright.so
4057f9b0 4057fa14
4057f9b4 000fb030
4057f9b8
4057f9bc a2b6fe79 /system/lib/libstagefright.so
4057f9c0 000fafe0
4057f9c4
4057f9c8 4057fa14
4057f9cc a2b6fe59 /system/lib/libstagefright.so
4057f9d0
4057f9d4 a801e509 /system/lib/libutils.so
4057f9d8 4057fa14
# 4057f9dc
4057f9e0
4057f9e4 000000a5
4057f9e8
4057f9ec aff17699 /system/lib/libc.so
4057f9f0 aff176a7 /system/lib/libc.so
4057f9f4
4057f9f8 aff0e154 /system/lib/libc.so
4057f9fc
4057fa00 aff0cf84 /system/lib/libc.so
4057fa04 aff0cf94 /system/lib/libc.so
4057fa08
4057fa0c 000000a5
4057fa10
4057fa14 aff0fca4 /system/lib/libc.so
4057fa18 662f9c00
4057fa1c 000000a5
4057fa20
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
pid: , tid:
r0 fffffe00 r1 c0186201 r2 be8b8b98 r3 be8b8b94
r4 0000f5e0 r5 0000f5b0 r6 0000f610 r7
r8 r9 0000f5cc 0000f5b8 fp
ip a812336c sp be8b8b78 lr aff25e19 pc aff0b680 cpsr
d0 000f891000000000 d1 00000004be8b8b00
d2 d3 00410049002e0000
d4 d5
d6 d7 0000000041a00000
d8 d9
d10 d11
d12 d13
d14 d15
d16 d17
d18 d19 3fcce7359d4792d9
d20 3f11504c292739d4 d21 bebbb371092382c4
d22 3ff0000000000000 d23 3ff43d135cda918c
d24 3e66376972bea4d0 d25
d26 d27
d28 d29
d30 d31
scr # pc 0000b680 /system/lib/libc.so (__ioctl)
# pc 00025e16 /system/lib/libc.so (ioctl)
# pc /system/lib/libbinder.so (_ZN7android14IPCThreadState14talkWithDriverEb)
# pc 00016afc /system/lib/libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb)
# pc 00008a94 /system/bin/mediaserver
# pc 00014aa0 /system/lib/libc.so (__libc_init) libc base address: aff00000 code around pc:
aff0b660 ef000000 e8bd0090 e1b00000 512fff1e
aff0b670 ea00b1ef e92d0090 e3a07036 ef000000
aff0b680 e8bd0090 e1b00000 512fff1e ea00b1e8
aff0b690 e92d0090 e3a07091 ef000000 e8bd0090
aff0b6a0 e1b00000 512fff1e ea00b1e1 e92d0090
...
可以看出,它同样包含很多重要的信息(特别是 stack )来帮助我们查找异常的原因。分析tombstone的方法,将单独成篇。
Android信号的产生和测试
我们看到,多数signal的产生是由于某种内部错误。我们在在开发过程中,当然也可以通过系统调用故意生成signal给某进程。主要的方法如果:
1. 在kernel里 使用 kill_proc_info()
2. 在native应用中 使用 kill() 或者raise()
3. java 应用中使用 Procees.sendSignal()等
但是在测试中,最简单的方法某过于通过 adb 工具了。一个典型场景是:
adb root
adb shell ps
adb shell kill -
首先是切换到root用户 (普通进程只能发个自己或者同组进程,而root可以发送signal给任何进程)。然后用 ps命令查看当前系统中所有的进程信息。最后用kill命令发送SIGQUIT给进程号为513的进程。
android kill程序的实现很简单,他只能支持发送signal的值(如上例中的 “3”)给进程,而不能用名字(如“SIGQUIT”)。 android 中kill程序的代码在system/core/toolbox/kill.c 中。虽然移植linux中kill的实现就能支持名字,但是那个完全没有必要,android需要的signal就这么几个,他们的值应该记住的。
对于终端发送 SIGQUIT,大多数用户可以直接得到预期的结果 (生成相应的trace文件)。 最困惑的行为来自于终端发送SIGILL, SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGSTKFLT等信号,我们常常看到 “不确定” 的行为:有时候能够看到 process 终止,有时候却不能。core dump 也不是总能产生。 例如如下测试场景:
adb root
adb shell ps
adb shell kill -
从 log里看到 进程299 并没有终止, ps 看到进程还在。Log只有如下输出:
F/libc ( ): Fatal signal (SIGSEGV) at 0x000001c0 (code=)
I/DEBUG ( ): timed out waiting for pid= tid= uid= to die
再试一次:
adb shell ps
adb shell kill -
这次 进程299被终止掉了,却没有产生 core dump文件:
D/Zygote ( ): Process terminated by signal ()
I/ActivityManager( ): Process com.android.calendar (pid ) has died.
其实,我们观察到得不确定行为是因为没有了解 android 这些信号的处理。他的行为的确是确定的,要点是:
要产生core dump并终止某进程,我们需要 连续发送两次改信号,并且中间间隔在0.2秒到3秒之间。
如果间隔过小, Android可能无法接收第一个signal。如果时间过久,android将简单的终止进程,而没有 core dump产生。 我们会在后面 详细的介绍产生这种行为的原因。
好了,了解到上面的行为后,我们再次试验,连续两次发送 SIGSEGV给进程,看看行为:
adb shell ps
adb shell kill -
adb shell kill -
我们看到, 该进程被终止, tombstone被打到log里, 并且存储在/data/tombstone_00 中:
F/libc ( ): Fatal signal (SIGSEGV) at 0x000001cf (code=)
I/DEBUG ( ): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG ( ): Build fingerprint: 'generic/sdk/generic:4.0.1/ICS_MR0/eng.drmn68.20111115.224016:eng/test-keys'
I/DEBUG ( ): pid: , tid: >>> com.android.mms <<<
I/DEBUG ( ): signal (SIGSEGV), code (?), fault addr 000001d2
I/DEBUG ( ): r0 fffffffc r1 beb2b4e0 r2 r3 ffffffff
I/DEBUG ( ): r4 001d0268 r5 001d027c r6 r7 000000fc
I/DEBUG ( ): r8 r9 fp beb2b674
I/DEBUG ( ): ip 400c11a4 sp beb2b4b8 lr 400b9993 pc cpsr
I/DEBUG ( ): d0 000000f043700000 d1 3ff0000043700000
I/DEBUG ( ): d2 457ff80000000fff d3 000000003f000000
I/DEBUG ( ): d4 00001fff00000000 d5 3fe999999999999a
I/DEBUG ( ): d6 3fe8000000000000 d7 000000f000000000
I/DEBUG ( ): d8 d9
I/DEBUG ( ): d10 d11
I/DEBUG ( ): d12 d13
I/DEBUG ( ): d14 d15
I/DEBUG ( ): scr
I/DEBUG ( ):
I/DEBUG ( ): # pc 0000d384 /system/lib/libc.so (epoll_wait)
I/DEBUG ( ): # pc /system/lib/libutils.so (_ZN7android6Looper9pollInnerEi)
I/DEBUG ( ): # pc 00026bbe /system/lib/libutils.so (_ZN7android6Looper8pollOnceEiPiS1_PPv) ...
至此,我们已经掌握 android信号的定义和行为。下面就可以研究产生这种行为的原因了。
Android 信号处理面面观 之 信号定义、行为和来源的更多相关文章
- Android 举例说明自己的定义Camera图片和预览,以及前后摄像头切换
如何调用本地图片,并调用系统拍摄的图像上一博文解释(http://blog.csdn.net/a123demi/article/details/40003695)的功能. 而本博文将通过实例实现自己定 ...
- 1.2 PCI总线的信号定义
PCI总线是一条共享总线,在一条PCI总线上可以挂接多个PCI设备.这些PCI设备通过一系列信号与PCI总线相连,这些信号由地址/数据信号.控制信号.仲裁信号.中断信号等多种信号组成. PCI总线是一 ...
- Android中怎样做到自己定义的广播仅仅能有指定的app接收
今天没吊事.又去面试了,详细哪家公司就不说了,由于我在之前的blog中注明了那些家公司的名字,结果人家给我私信说我泄露他们的题目.好吧,我错了... 事实上当我们已经在工作的时候.我们能够在空暇的时间 ...
- Android画图系列(二)——自己定义View绘制基本图形
这个系列主要是介绍下Android自己定义View和Android画图机制.自己能力有限.假设在介绍过程中有什么错误.欢迎指正 前言 在上一篇Android画图系列(一)--自己定义View基础中我们 ...
- 003android初级篇之【转】Android开发中颜色的定义方法
正好用到颜色的定义,但脑子里没有记住具体,转载一篇加强印象 1.使用Color类的常量,如: int color = Color.BLUE; // 创建一个蓝色 是使用Android提供的颜色 int ...
- android CheckBox控件的定义及事件监听
http://www.beijibear.com/index.php?aid=336 android CheckBox控件的定义及事件监听,本例实现CheckBox控件的定义及点击事件的监听并显示结果 ...
- Android 升级下载 它们的定义Updates 兼容版本
Android 更新模块 它们的定义Update 写这个总结是由于在项目中碰到了Android系统兼容的BUG Android项目原本使用的是API提供的下载方法 例如以下: Download ...
- Android.mk中添加宏定义
在Boardconfig.mk 中添加一个 IS_FLAG := true 由于Boardconfig.mk和各目录的Android.mk是相互关联的 所以我们可以在Android.mk 中添加 一个 ...
- Android——inflate 将一个xml中定义的布局找出来
通俗的说,inflate就相当于将一个xml中定义的布局找出来. 因为在一个Activity里如果直接用findViewById()的话,对应的是setConentView()的那个layout里的组 ...
随机推荐
- [原创]H5前端性能测试工具介绍
[原创H5前端性能测试工具介绍 一 网络抓包工具 网络抓包工具选择原则,可以捕获网络请求,抓取具体请求信息流,同时可以针对网络请包进行修改或拦截: 1.Fiddler(推荐) 2.Charles(推荐 ...
- how to generate an analog output from a in-built pwm of Atmega 32AVR microcontrloller?
how to generate an analog output from a in-built pwm of Atmega 32AVR microcontrloller? you need a re ...
- TThread深入分析
Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是 对TThread类的几个成员作一简单介绍,再说明一下Execute的实现和Synch ...
- Intellij IDEA 自动清除无效 import 和 清除无效 import 的快捷键 ctrl+alt+o
快捷键 ctrl+alt+o 自动清除的配置方法 可以settings-general-auto import-java项,勾选optimize imports on the fly,在当前项目下会自 ...
- cache line 伪共享
https://blog.csdn.net/qq_27680317/article/details/78486220认识CPU Cache CPU Cache概述 随着CPU的频率不断提升,而内存的访 ...
- 在 Visual Studio 生成项目时,会发现一些 dll 并没有被复制到输出目录,导致最终程序的执行错误
发现与解决 检查了一下项目文件,发现是因为这些 dll 文件的引用其中一个叫做 嵌入互操作类型(EmbedInteropTypes)的属性被设为了 True,此时 复制本地 属性会被强制设为 Fals ...
- Python--Redis实战:第四章:数据安全与性能保障:第7节:非事务型流水线
之前章节首次介绍multi和exec的时候讨论过它们的”事务“性质:被multi和exec包裹的命令在执行时不会被其他客户端打扰.而使用事务的其中一个好处就是底层的客户端会通过使用流水线来提高事务执行 ...
- Fluent动网格【1】:概述
最近总有小伙伴向我询问Fluent中的动网格问题,因此决定做一期关于Fluent动网格技术的内容. 动网格技术在流体仿真中很特殊,应用也很广.生活中能够碰到形形色色的包含有部件运动的问题,比如说我现在 ...
- linux每日命令(17):which命令
我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which 查看可执行文件的位置. whereis 查看文件的位置. locate 配合数据库查看文件位置. f ...
- 安装polyglot出错
安装polyglot出错 错误 Complete output from command python setup.py egg_info: Traceback (most recent call l ...