传统 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)中:

  1. /*Signals.*/
  2. #defineSIGHUP1/*Hangup(POSIX).*/
  3. #defineSIGINT2/*Interrupt(ANSI).*/
  4. #defineSIGQUIT3/*Quit(POSIX).*/
  5. #defineSIGILL4/*Illegalinstruction(ANSI).*/
  6. #defineSIGTRAP5/*Tracetrap(POSIX).*/
  7. #defineSIGABRT6/*Abort(ANSI).*/
  8. #defineSIGIOT6/*IOTtrap(4.2BSD).*/
  9. #defineSIGBUS7/*BUSerror(4.2BSD).*/
  10. #defineSIGFPE8/*Floating-pointexception(ANSI).*/
  11. #defineSIGKILL9/*Kill,unblockable(POSIX).*/
  12. #defineSIGUSR110/*User-definedsignal1(POSIX).*/
  13. #defineSIGSEGV11/*Segmentationviolation(ANSI).*/
  14. #defineSIGUSR212/*User-definedsignal2(POSIX).*/
  15. #defineSIGPIPE13/*Brokenpipe(POSIX).*/
  16. #defineSIGALRM14/*Alarmclock(POSIX).*/
  17. #defineSIGTERM15/*Termination(ANSI).*/
  18. #defineSIGSTKFLT16/*Stackfault.*/
  19. #defineSIGCLDSIGCHLD/*SameasSIGCHLD(SystemV).*/
  20. #defineSIGCHLD17/*Childstatushaschanged(POSIX).*/
  21. #defineSIGCONT18/*Continue(POSIX).*/
  22. #defineSIGSTOP19/*Stop,unblockable(POSIX).*/
  23. #defineSIGTSTP20/*Keyboardstop(POSIX).*/
  24. #defineSIGTTIN21/*Backgroundreadfromtty(POSIX).*/
  25. #defineSIGTTOU22/*Backgroundwritetotty(POSIX).*/
  26. #defineSIGURG23/*Urgentconditiononsocket(4.2BSD).*/
  27. #defineSIGXCPU24/*CPUlimitexceeded(4.2BSD).*/
  28. #defineSIGXFSZ25/*Filesizelimitexceeded(4.2BSD).*/
  29. #defineSIGVTALRM26/*Virtualalarmclock(4.2BSD).*/
  30. #defineSIGPROF27/*Profilingalarmclock(4.2BSD).*/
  31. #defineSIGWINCH28/*Windowsizechange(4.3BSD,Sun).*/
  32. #defineSIGPOLLSIGIO/*Pollableeventoccurred(SystemV).*/
  33. #defineSIGIO29/*I/Onowpossible(4.2BSD).*/
  34. #defineSIGPWR30/*Powerfailurerestart(SystemV).*/
  35. #defineSIGSYS31/*Badsystemcall.*/
  36. #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文件的内容:

  1. -----pid503at2011-11-2121:59:12-----
  2. Cmdline:com.Android.phone
  3. DALVIKTHREADS:
  4. (mutexes:tll=0tsl=0tscl=0ghl=0hwl=0hwll=0)
  5. "main"prio=5tid=1NATIVE
  6. |group="main"sCount=1dsCount=0obj=0x400246a0self=0x12770
  7. |sysTid=503nice=0sched=0/0cgrp=defaulthandle=-1342909272
  8. |schedstat=(151650390251219723525823068)utm=182stm=1334core=0
  9. atAndroid.os.MessageQueue.nativePollOnce(NativeMethod)
  10. atAndroid.os.MessageQueue.next(MessageQueue.java:119)
  11. atAndroid.os.Looper.loop(Looper.java:122)
  12. atAndroid.app.ActivityThread.main(ActivityThread.java:4134)
  13. atjava.lang.reflect.Method.invokeNative(NativeMethod)
  14. atjava.lang.reflect.Method.invoke(Method.java:491)
  15. atcom.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
  16. atcom.Android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
  17. atdalvik.system.NativeStart.main(NativeMethod)
  18. "Thread-29"prio=5tid=24WAIT
  19. |group="main"sCount=1dsCount=0obj=0x406f0d50self=0x208c18
  20. |sysTid=1095nice=0sched=0/0cgrp=defaulthandle=2133304
  21. |schedstat=(95214837029937750720)utm=0stm=0core=0
  22. atjava.lang.Object.wait(NativeMethod)
  23. -waitingon<0x406f0d50>(acom.motorola.Android.telephony.cdma.OemCdmaTelephonyManager$Watchdog)
  24. atjava.lang.Object.wait(Object.java:361)
  25. atcom.motorola.Android.telephony.cdma.OemCdmaTelephonyManager$Watchdog.run(OemCdmaTelephonyManager.java:229)
  26. "FileObserver"prio=5tid=23NATIVE
  27. |group="main"sCount=1dsCount=0obj=0x4068b2f8self=0x1ed278
  28. |sysTid=909nice=0sched=0/0cgrp=defaulthandle=2019248
  29. |schedstat=(118102917018493670720)utm=0stm=0core=0
  30. atAndroid.os.FileObserver$ObserverThread.observe(NativeMethod)
  31. atAndroid.os.FileObserver$ObserverThread.run(FileObserver.java:88)
  32. "Android.hardware.SensorManager$SensorThread"prio=5tid=22NATIVE
  33. |group="main"sCount=1dsCount=0obj=0x406bbd90self=0x1b2ec0
  34. |sysTid=869nice=-8sched=0/0cgrp=defaulthandle=1974064
  35. |schedstat=(3014251483829598993315621)utm=171stm=128core=0
  36. atAndroid.hardware.SensorManager.sensors_data_poll(NativeMethod)
  37. atAndroid.hardware.SensorManager$SensorThread$SensorThreadRunnable.run(SensorManager.java:498)
  38. atjava.lang.Thread.run(Thread.java:1020)
  39. ...
该文件包好很多重要的信息,可以说明在发生异常是,当前进程的状态 (后面有单独的一篇文章分析改文件)


2. 对于很多其他的异常信号 (SIGILL, SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGSTKFLT ), Android进程 在退出前,会生成 tombstone文件。记录该进程退出前的轨迹。一个典型的tombstone文件内容如下:

  1. ************************************************
  2. Buildfingerprint:'verizon/pasteur/pasteur:3.2.2/1.6.0_241/eng.drmn68.20111115.094123:eng/test-keys'
  3. pid:181,tid:322>>>/system/bin/mediaserver<<<
  4. signal8(SIGFPE),code0(?),faultaddr000000b5
  5. r000000000r100000008r2ffffffffr300000020
  6. r400000008r500000000r6000000a5r700000025
  7. r8662f9c00r9662f9c001000000001fp00000000
  8. ipaff17699sp4057f9dclraff176a7pcaff0c684cpsr00000010
  9. d06f762f6f69647502d10000562202000000
  10. d20000000400000300d3400120dc00000000
  11. d40000000000000000d50000000000000000
  12. d63ce449db86666666d73e4ccccd3e4ccccd
  13. d8000000000035c6a8d9000000000035c6a8
  14. d100000000000000000d110000000000000000
  15. d120000000000000000d130000000000000000
  16. d140000000000000000d150000000000000000
  17. d160000000000000000d173e582f8f86b6a000
  18. d183fe0000000000000d193fe000000c17c7c3
  19. d203f11504c292739d4d21bebbb371092382c4
  20. d223ff0000000000000d233ff43d135cda918c
  21. d243e66376972bea4d0d250000000000000000
  22. d260000000000000000d270000000000000000
  23. d280000000000000000d290000000000000000
  24. d300000000000000000d310000000000000000
  25. scr20000010
  26. #00pc0000c684/system/lib/libc.so(kill)
  27. #01pc000176a4/system/lib/libc.so(raise)
  28. libcbaseaddress:aff00000
  29. codearoundpc:
  30. aff0c664e2601000e0100001116f0f1012600020
  31. aff0c674e12fff1ee92d50f0e3a07025ef000000
  32. aff0c684e8bd50f0e1b00000512fff1eea00ade7
  33. aff0c694e92d50f0e3a070eeef000000e8bd50f0
  34. aff0c6a4e1b00000512fff1eea00ade0f5d0f000
  35. codearoundlr:
  36. aff1768400029e2e461cb537e9cd17ddf7f34500
  37. aff17694bd3eef024604b510ed5ef7f3f7f44621
  38. aff176a4bd10efea490346022300b510f7f44802
  39. aff176b4bd10edf628121969fee1dead2400b513
  40. aff176c494019400ec9cf7f4bf00bd1c4c11b570
  41. stack:
  42. 4057f99ca2b6fd15/system/lib/libstagefright.so
  43. 4057f9a000000000
  44. 4057f9a4a2b6fe51/system/lib/libstagefright.so
  45. 4057f9a8000fb02c
  46. 4057f9aca2b6fde7/system/lib/libstagefright.so
  47. 4057f9b04057fa14
  48. 4057f9b4000fb030
  49. 4057f9b800000000
  50. 4057f9bca2b6fe79/system/lib/libstagefright.so
  51. 4057f9c0000fafe0
  52. 4057f9c400000000
  53. 4057f9c84057fa14
  54. 4057f9cca2b6fe59/system/lib/libstagefright.so
  55. 4057f9d000000001
  56. 4057f9d4a801e509/system/lib/libutils.so
  57. 4057f9d84057fa14
  58. #014057f9dc00000008
  59. 4057f9e000000000
  60. 4057f9e4000000a5
  61. 4057f9e800000000
  62. 4057f9ecaff17699/system/lib/libc.so
  63. 4057f9f0aff176a7/system/lib/libc.so
  64. 4057f9f400000000
  65. 4057f9f8aff0e154/system/lib/libc.so
  66. 4057f9fc00000000
  67. 4057fa00aff0cf84/system/lib/libc.so
  68. 4057fa04aff0cf94/system/lib/libc.so
  69. 4057fa0800000000
  70. 4057fa0c000000a5
  71. 4057fa1000000000
  72. 4057fa14aff0fca4/system/lib/libc.so
  73. 4057fa18662f9c00
  74. 4057fa1c000000a5
  75. 4057fa2000000000
  76. ------------------------------------------------
  77. pid:181,tid:181
  78. r0fffffe00r1c0186201r2be8b8b98r3be8b8b94
  79. r40000f5e0r50000f5b0r60000f610r700000036
  80. r800000001r90000f5cc100000f5b8fp00000000
  81. ipa812336cspbe8b8b78lraff25e19pcaff0b680cpsr80000010
  82. d0000f891000000000d100000004be8b8b00
  83. d20069006400650000d300410049002e0000
  84. d40000000000000000d50000000000000000
  85. d64208000041880000d70000000041a00000
  86. d80000000000000000d90000000000000000
  87. d100000000000000000d110000000000000000
  88. d120000000000000000d130000000000000000
  89. d140000000000000000d150000000000000000
  90. d160000000000000000d170000000000000000
  91. d184000000000000000d193fcce7359d4792d9
  92. d203f11504c292739d4d21bebbb371092382c4
  93. d223ff0000000000000d233ff43d135cda918c
  94. d243e66376972bea4d0d250000000000000000
  95. d260000000000000000d270000000000000000
  96. d280000000000000000d290000000000000000
  97. d300000000000000000d310000000000000000
  98. scr60000010
  99. #00pc0000b680/system/lib/libc.so(__ioctl)
  100. #01pc00025e16/system/lib/libc.so(ioctl)
  101. #02pc00016202/system/lib/libbinder.so(_ZN7Android14IPCThreadState14talkWithDriverEb)
  102. #03pc00016afc/system/lib/libbinder.so(_ZN7Android14IPCThreadState14joinThreadPoolEb)
  103. #04pc00008a94/system/bin/mediaserver
  104. #05pc00014aa0/system/lib/libc.so(__libc_init)
  105. libcbaseaddress:aff00000
  106. codearoundpc:
  107. aff0b660ef000000e8bd0090e1b00000512fff1e
  108. aff0b670ea00b1efe92d0090e3a07036ef000000
  109. aff0b680e8bd0090e1b00000512fff1eea00b1e8
  110. aff0b690e92d0090e3a07091ef000000e8bd0090
  111. aff0b6a0e1b00000512fff1eea00b1e1e92d0090
  112. ...
可以看出,它同样包含很多重要的信息(特别是 stack )来帮助我们查找异常的原因。分析 tombstone的方法,将单独成篇。


Android信号的产生和测试

我们看到,多数signal的产生是由于某种内部错误。我们在在开发过程中,当然也可以通过系统调用故意生成signal给某进程。主要的方法如果:

1. 在kernel里 使用 kill_proc_info()

2. 在native应用中 使用 kill() 或者raise()

3. java 应用中使用 Procees.sendSignal()等

但是在测试中,最简单的方法某过于通过 adb 工具了。一个典型场景是:

  1. adbroot
  2. adbshellps
  3. 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


更多相关文章

  1. Android(安卓)OTA 升级之三:生成recovery.img
  2. Android(安卓)应用程序组件学习
  3. android嵌入式底层开发
  4. Android系统工具之Monkey自动化测试
  5. Android(安卓)FOTA 升级流程
  6. Android弹幕实现:基于B站弹幕开源系统(2)
  7. 在Ubuntu上下载、编译、运行Android内核Linux Kernel
  8. android broadcastReceiver生命周期及两种应用
  9. Android(安卓)的核心服务

随机推荐

  1. android—label窗口——基础编
  2. Android(安卓)中使用 ServiceLoader、Aut
  3. archlinux 64bit 开发android
  4. react-native-splash-screen--RN 0.5以上
  5. 一步一步写一个简单通用的makefile(四)--
  6. android 顶部横向滑动菜单效果
  7. android打开手机相册获取真正的图片路径
  8. runOnUiThread
  9. 【Android(安卓)开发教程】使用Intent调
  10. SQLiteDatabase中的query方法,里面有个用