Android(安卓)信号处理面面观 之 信号定义、行为和来源
传统 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.*/
- #defineSIGHUP1/*Hangup(POSIX).*/
- #defineSIGINT2/*Interrupt(ANSI).*/
- #defineSIGQUIT3/*Quit(POSIX).*/
- #defineSIGILL4/*Illegalinstruction(ANSI).*/
- #defineSIGTRAP5/*Tracetrap(POSIX).*/
- #defineSIGABRT6/*Abort(ANSI).*/
- #defineSIGIOT6/*IOTtrap(4.2BSD).*/
- #defineSIGBUS7/*BUSerror(4.2BSD).*/
- #defineSIGFPE8/*Floating-pointexception(ANSI).*/
- #defineSIGKILL9/*Kill,unblockable(POSIX).*/
- #defineSIGUSR110/*User-definedsignal1(POSIX).*/
- #defineSIGSEGV11/*Segmentationviolation(ANSI).*/
- #defineSIGUSR212/*User-definedsignal2(POSIX).*/
- #defineSIGPIPE13/*Brokenpipe(POSIX).*/
- #defineSIGALRM14/*Alarmclock(POSIX).*/
- #defineSIGTERM15/*Termination(ANSI).*/
- #defineSIGSTKFLT16/*Stackfault.*/
- #defineSIGCLDSIGCHLD/*SameasSIGCHLD(SystemV).*/
- #defineSIGCHLD17/*Childstatushaschanged(POSIX).*/
- #defineSIGCONT18/*Continue(POSIX).*/
- #defineSIGSTOP19/*Stop,unblockable(POSIX).*/
- #defineSIGTSTP20/*Keyboardstop(POSIX).*/
- #defineSIGTTIN21/*Backgroundreadfromtty(POSIX).*/
- #defineSIGTTOU22/*Backgroundwritetotty(POSIX).*/
- #defineSIGURG23/*Urgentconditiononsocket(4.2BSD).*/
- #defineSIGXCPU24/*CPUlimitexceeded(4.2BSD).*/
- #defineSIGXFSZ25/*Filesizelimitexceeded(4.2BSD).*/
- #defineSIGVTALRM26/*Virtualalarmclock(4.2BSD).*/
- #defineSIGPROF27/*Profilingalarmclock(4.2BSD).*/
- #defineSIGWINCH28/*Windowsizechange(4.3BSD,Sun).*/
- #defineSIGPOLLSIGIO/*Pollableeventoccurred(SystemV).*/
- #defineSIGIO29/*I/Onowpossible(4.2BSD).*/
- #defineSIGPWR30/*Powerfailurerestart(SystemV).*/
- #defineSIGSYS31/*Badsystemcall.*/
- #defineSIGUNUSED31
我们知道,信号处理的方式一般有三种:
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文件的内容:
- -----pid503at2011-11-2121:59:12-----
- Cmdline:com.Android.phone
- DALVIKTHREADS:
- (mutexes:tll=0tsl=0tscl=0ghl=0hwl=0hwll=0)
- "main"prio=5tid=1NATIVE
- |group="main"sCount=1dsCount=0obj=0x400246a0self=0x12770
- |sysTid=503nice=0sched=0/0cgrp=defaulthandle=-1342909272
- |schedstat=(151650390251219723525823068)utm=182stm=1334core=0
- atAndroid.os.MessageQueue.nativePollOnce(NativeMethod)
- atAndroid.os.MessageQueue.next(MessageQueue.java:119)
- atAndroid.os.Looper.loop(Looper.java:122)
- atAndroid.app.ActivityThread.main(ActivityThread.java:4134)
- atjava.lang.reflect.Method.invokeNative(NativeMethod)
- atjava.lang.reflect.Method.invoke(Method.java:491)
- atcom.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
- atcom.Android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
- atdalvik.system.NativeStart.main(NativeMethod)
- "Thread-29"prio=5tid=24WAIT
- |group="main"sCount=1dsCount=0obj=0x406f0d50self=0x208c18
- |sysTid=1095nice=0sched=0/0cgrp=defaulthandle=2133304
- |schedstat=(95214837029937750720)utm=0stm=0core=0
- atjava.lang.Object.wait(NativeMethod)
- -waitingon<0x406f0d50>(acom.motorola.Android.telephony.cdma.OemCdmaTelephonyManager$Watchdog)
- atjava.lang.Object.wait(Object.java:361)
- atcom.motorola.Android.telephony.cdma.OemCdmaTelephonyManager$Watchdog.run(OemCdmaTelephonyManager.java:229)
- "FileObserver"prio=5tid=23NATIVE
- |group="main"sCount=1dsCount=0obj=0x4068b2f8self=0x1ed278
- |sysTid=909nice=0sched=0/0cgrp=defaulthandle=2019248
- |schedstat=(118102917018493670720)utm=0stm=0core=0
- atAndroid.os.FileObserver$ObserverThread.observe(NativeMethod)
- atAndroid.os.FileObserver$ObserverThread.run(FileObserver.java:88)
- "Android.hardware.SensorManager$SensorThread"prio=5tid=22NATIVE
- |group="main"sCount=1dsCount=0obj=0x406bbd90self=0x1b2ec0
- |sysTid=869nice=-8sched=0/0cgrp=defaulthandle=1974064
- |schedstat=(3014251483829598993315621)utm=171stm=128core=0
- atAndroid.hardware.SensorManager.sensors_data_poll(NativeMethod)
- atAndroid.hardware.SensorManager$SensorThread$SensorThreadRunnable.run(SensorManager.java:498)
- atjava.lang.Thread.run(Thread.java:1020)
- ...
2. 对于很多其他的异常信号 (SIGILL, SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGSTKFLT ), Android进程 在退出前,会生成 tombstone文件。记录该进程退出前的轨迹。一个典型的tombstone文件内容如下:
- ************************************************
- Buildfingerprint:'verizon/pasteur/pasteur:3.2.2/1.6.0_241/eng.drmn68.20111115.094123:eng/test-keys'
- pid:181,tid:322>>>/system/bin/mediaserver<<<
- signal8(SIGFPE),code0(?),faultaddr000000b5
- r000000000r100000008r2ffffffffr300000020
- r400000008r500000000r6000000a5r700000025
- r8662f9c00r9662f9c001000000001fp00000000
- ipaff17699sp4057f9dclraff176a7pcaff0c684cpsr00000010
- d06f762f6f69647502d10000562202000000
- d20000000400000300d3400120dc00000000
- d40000000000000000d50000000000000000
- d63ce449db86666666d73e4ccccd3e4ccccd
- d8000000000035c6a8d9000000000035c6a8
- d100000000000000000d110000000000000000
- d120000000000000000d130000000000000000
- d140000000000000000d150000000000000000
- d160000000000000000d173e582f8f86b6a000
- d183fe0000000000000d193fe000000c17c7c3
- d203f11504c292739d4d21bebbb371092382c4
- d223ff0000000000000d233ff43d135cda918c
- d243e66376972bea4d0d250000000000000000
- d260000000000000000d270000000000000000
- d280000000000000000d290000000000000000
- d300000000000000000d310000000000000000
- scr20000010
- #00pc0000c684/system/lib/libc.so(kill)
- #01pc000176a4/system/lib/libc.so(raise)
- libcbaseaddress:aff00000
- codearoundpc:
- aff0c664e2601000e0100001116f0f1012600020
- aff0c674e12fff1ee92d50f0e3a07025ef000000
- aff0c684e8bd50f0e1b00000512fff1eea00ade7
- aff0c694e92d50f0e3a070eeef000000e8bd50f0
- aff0c6a4e1b00000512fff1eea00ade0f5d0f000
- codearoundlr:
- aff1768400029e2e461cb537e9cd17ddf7f34500
- aff17694bd3eef024604b510ed5ef7f3f7f44621
- aff176a4bd10efea490346022300b510f7f44802
- aff176b4bd10edf628121969fee1dead2400b513
- aff176c494019400ec9cf7f4bf00bd1c4c11b570
- stack:
- 4057f99ca2b6fd15/system/lib/libstagefright.so
- 4057f9a000000000
- 4057f9a4a2b6fe51/system/lib/libstagefright.so
- 4057f9a8000fb02c
- 4057f9aca2b6fde7/system/lib/libstagefright.so
- 4057f9b04057fa14
- 4057f9b4000fb030
- 4057f9b800000000
- 4057f9bca2b6fe79/system/lib/libstagefright.so
- 4057f9c0000fafe0
- 4057f9c400000000
- 4057f9c84057fa14
- 4057f9cca2b6fe59/system/lib/libstagefright.so
- 4057f9d000000001
- 4057f9d4a801e509/system/lib/libutils.so
- 4057f9d84057fa14
- #014057f9dc00000008
- 4057f9e000000000
- 4057f9e4000000a5
- 4057f9e800000000
- 4057f9ecaff17699/system/lib/libc.so
- 4057f9f0aff176a7/system/lib/libc.so
- 4057f9f400000000
- 4057f9f8aff0e154/system/lib/libc.so
- 4057f9fc00000000
- 4057fa00aff0cf84/system/lib/libc.so
- 4057fa04aff0cf94/system/lib/libc.so
- 4057fa0800000000
- 4057fa0c000000a5
- 4057fa1000000000
- 4057fa14aff0fca4/system/lib/libc.so
- 4057fa18662f9c00
- 4057fa1c000000a5
- 4057fa2000000000
- ------------------------------------------------
- pid:181,tid:181
- r0fffffe00r1c0186201r2be8b8b98r3be8b8b94
- r40000f5e0r50000f5b0r60000f610r700000036
- r800000001r90000f5cc100000f5b8fp00000000
- ipa812336cspbe8b8b78lraff25e19pcaff0b680cpsr80000010
- d0000f891000000000d100000004be8b8b00
- d20069006400650000d300410049002e0000
- d40000000000000000d50000000000000000
- d64208000041880000d70000000041a00000
- d80000000000000000d90000000000000000
- d100000000000000000d110000000000000000
- d120000000000000000d130000000000000000
- d140000000000000000d150000000000000000
- d160000000000000000d170000000000000000
- d184000000000000000d193fcce7359d4792d9
- d203f11504c292739d4d21bebbb371092382c4
- d223ff0000000000000d233ff43d135cda918c
- d243e66376972bea4d0d250000000000000000
- d260000000000000000d270000000000000000
- d280000000000000000d290000000000000000
- d300000000000000000d310000000000000000
- scr60000010
- #00pc0000b680/system/lib/libc.so(__ioctl)
- #01pc00025e16/system/lib/libc.so(ioctl)
- #02pc00016202/system/lib/libbinder.so(_ZN7Android14IPCThreadState14talkWithDriverEb)
- #03pc00016afc/system/lib/libbinder.so(_ZN7Android14IPCThreadState14joinThreadPoolEb)
- #04pc00008a94/system/bin/mediaserver
- #05pc00014aa0/system/lib/libc.so(__libc_init)
- libcbaseaddress:aff00000
- codearoundpc:
- aff0b660ef000000e8bd0090e1b00000512fff1e
- aff0b670ea00b1efe92d0090e3a07036ef000000
- aff0b680e8bd0090e1b00000512fff1eea00b1e8
- aff0b690e92d0090e3a07091ef000000e8bd0090
- aff0b6a0e1b00000512fff1eea00b1e1e92d0090
- ...
Android信号的产生和测试
我们看到,多数signal的产生是由于某种内部错误。我们在在开发过程中,当然也可以通过系统调用故意生成signal给某进程。主要的方法如果:
1. 在kernel里 使用 kill_proc_info()
2. 在native应用中 使用 kill() 或者raise()
3. java 应用中使用 Procees.sendSignal()等
但是在测试中,最简单的方法某过于通过 adb 工具了。一个典型场景是:
- adbroot
- adbshellps
- adbshellkill-3513
首先是切换到root用户 (普通进程只能发个自己或者同组进程,而root可以发送signal给任何进程)。然后用 ps命令查看当前系统中所有的进程信息。最后用kill命令发送SIGQUIT给进程号为513的进程。
Android kill程序的实现很简单,他只能支持发送signal的值(如上例中的 “3”)给进程,而不能用名字(如“SIGQUIT”)。 android 中kill程序的代码在system/core/toolbox/kill.c 中。虽然移植linux中kill的实现就能支持名字,但是那个完全没有必要,android需要的signal就这么几个,他们的值应该记住的。
from: http://www.linuxidc.com/Linux/2011-11/47807.htm
更多相关文章
- Android(安卓)OTA 升级之三:生成recovery.img
- Android(安卓)应用程序组件学习
- android嵌入式底层开发
- Android系统工具之Monkey自动化测试
- Android(安卓)FOTA 升级流程
- Android弹幕实现:基于B站弹幕开源系统(2)
- 在Ubuntu上下载、编译、运行Android内核Linux Kernel
- android broadcastReceiver生命周期及两种应用
- Android(安卓)的核心服务