repost from:http://www.cjjjs.com/paper/xmkf/2017817141130842.html
很多用户认为进程异常终止情况无从分析,但实际上进程异常终止情况都是有迹可寻的. 所有的进程异常终止行为,都是通过内核发信号给特定进程或进程组实现的. 可分成几个类型进行描述:
- SIGKILL. SIGKILL最特殊,因为该信号不可被捕获,同时SIGKILL不会导致被终止的进程产生core文件, 但如果真正的是由内核中发出的SIGKILL,则内核一定会在dmesg中记录下信息. 另外在内核中使用SIGKILL的地方屈指可数,如oom_kill_process()中, 所以通过dmesg记录并且分析内核中使用SIGKILL的代码,并不难分析原因- SIGQUIT, SIGILL, SIGABRT, SIGBUS, SIGFPE, SIGSEGV. 这几个信号在保留情况下会终止进程并会产生core文件, 用户根据core中的stack trace信息,能直接定位出导致终止信号的代码位置. 另外, SIGQUIT,SIGABRT一般是由用户代码自己使用的,好的代码一般会记录日志. SIGILL, SIGBUS, SIGFPE, SIGSEGV, 都是由内核中产生的,搜索内核源码,不难列出内核中使用这几个信号的地方, 如SIGILL 是非法指令,可能是浮点运算产生的代码被corrupted或文本区域的物理内存corruption; SIGBUS多由MCE故障定位导致; SIGSEGV多由应用代码的指针变量被corrupted导致. 对于应用的heap或stack的内存被corrupted, 可用valgrind工具对应用进行profile, 通常能直接发现导致corruption的代码
- SIGINT, SIGPIPE, SIGALRM, SIGTERM. 这几个信号在保留情况下终止进程但不会产生core文件. 对这几个信号,建议用户一定要定义一个handler,以记录产生问题的上下文. 比较容易忽略的是SIGPIPE, 很多用户程序在使用select()或poll()时只监听read/write描述符,不监听exception描述符,在对方TCP已经关闭的情况下,仍然向socket中写入,导致SIGPIPE.
- 对于恶意的代吗产生的进程终止行为,如合作的一些进程中,A向B发SIGKILL, 而没做日志记录,或者B直接判断某条件而调用exit(), 也没有做日志记录.在应用代码量很大的情况下,通过分析代码故障定位这种情形也许很难. SystemTap提供了解决这个问题的一个比较好的方法,就是写用户层的probes, 追踪进程对signal(), exit() 等系统调用的使用.
Signal
|
Description
|
SIGABRT
|
由调用abort函数产生,进程非正常退出
|
SIGALRM
|
用alarm函数设置的timer超时或setitimer函数设置的interval timer超时
|
SIGBUS
|
某种特定的硬件异常,通常由内存访问引起
|
SIGCANCEL
|
由Solaris Thread Library内部使用,通常不会使用
|
SIGCHLD
|
进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略
|
SIGCONT
|
当被stop的进程恢复运行的时候,自动发送
|
SIGEMT
|
和实现相关的硬件异常
|
SIGFPE
|
数学相关的异常,如被0除,浮点溢出,等等
|
SIGFREEZE
|
Solaris专用,Hiberate或者Suspended时候发送
|
SIGHUP
|
发送给具有Terminal的Controlling Process,当terminal被disconnect时候发送
|
SIGILL
|
非法指令异常
|
SIGINFO
|
BSD signal。由Status Key产生,通常是CTRL+T。发送给所有Foreground Group的进程
|
SIGINT
|
由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程
|
SIGIO
|
异步IO事件
|
SIGIOT
|
实现相关的硬件异常,一般对应SIGABRT
|
SIGKILL
|
无法处理和忽略。中止某个进程
|
SIGLWP
|
由Solaris Thread Libray内部使用
|
SIGPIPE
|
在reader中止之后写Pipe的时候发送
|
SIGPOLL
|
当某个事件发送给Pollable Device的时候发送
|
SIGPROF
|
Setitimer指定的Profiling Interval Timer所产生
|
SIGPWR
|
和系统相关。和UPS相关。
|
SIGQUIT
|
输入Quit Key的时候(CTRL+\)发送给所有Foreground Group的进程
|
SIGSEGV
|
非法内存访问
|
SIGSTKFLT
|
Linux专用,数学协处理器的栈异常
|
SIGSTOP
|
中止进程。无法处理和忽略。
|
SIGSYS
|
非法系统调用
|
SIGTERM
|
请求中止进程,kill命令缺省发送
|
SIGTHAW
|
Solaris专用,从Suspend恢复时候发送
|
SIGTRAP
|
实现相关的硬件异常。一般是调试异常
|
SIGTSTP
|
Suspend Key,一般是Ctrl+Z。发送给所有Foreground Group的进程
|
SIGTTIN
|
当Background Group的进程尝试读取Terminal的时候发送
|
SIGTTOU
|
当Background Group的进程尝试写Terminal的时候发送
|
SIGURG
|
当out-of-band data接收的时候可能发送
|
SIGUSR1
|
用户自定义signal 1
|
SIGUSR2
|
用户自定义signal 2
|
SIGVTALRM
|
setitimer函数设置的Virtual Interval Timer超时的时候
|
SIGWAITING
|
Solaris Thread Library内部实现专用
|
SIGWINCH
|
当Terminal的窗口大小改变的时候,发送给Foreground Group的所有进程
|
SIGXCPU
|
当CPU时间限制超时的时候
|
SIGXFSZ
|
进程超过文件大小限制
|
SIGXRES
|
Solaris专用,进程超过资源限制的时候发送
|
signal对应的值:
POSIX.1中列出的信号:
SIGHUP 1 A 终端挂起或者控制进程终止
SIGINT 2 A 键盘中断(如break键被按下)
SIGQUIT 3 C 键盘的退出键被按下
SIGILL 4 C 非法指令
SIGABRT 6 C 由abort(3)发出的退出指令
SIGFPE 8 C 浮点异常
SIGKILL 9 AEF Kill信号
SIGSEGV 11 C 无效的内存引用
SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道
SIGALRM 14 A 由alarm(2)发出的信号
SIGTERM 15 A 终止信号
SIGUSR1 30,10,16 A 用户自定义信号1
SIGUSR2 31,12,17 A 用户自定义信号2
SIGCHLD 20,17,18 B 子进程结束信号
SIGCONT 19,18,25 进程继续(曾被停止的进程)
SIGSTOP 17,19,23 DEF 终止进程
SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键
SIGTTIN 21,21,26 D 后台进程企图从控制终端读
SIGTTOU 22,22,27 D 后台进程企图从控制终端写
没在POSIX.1中列出,而在SUSv2列出
SIGBUS 10,7,10 C 总线错误(错误的内存访问)
SIGPOLL A Sys V定义的Pollable事件,与SIGIO同义
SIGPROF 27,27,29 A Profiling定时器到
SIGSYS 12,-,12 C 无效的系统调用 (SVID)
SIGTRAP 5 C 跟踪/断点捕获
SIGURG 16,23,21 B Socket出现紧急条件(4.2 BSD)
SIGVTALRM 26,26,28 A 实际时间报警时钟信号(4.2 BSD)
SIGXCPU 24,24,30 C 超出设定的CPU时间限制(4.2 BSD)
SIGXFSZ 25,25,31 C 超出设定的文件大小限制(4.2 BSD)
(对于SIGSYS,SIGXCPU,SIGXFSZ,以及某些机器体系结构下的SIGBUS,Linux缺省的动作是A (terminate),SUSv2 是C (terminate and dump core))。
下面是其它的一些信号
信号 值 处理动作 发出信号的原因
----------------------------------------------------------------------
SIGIOT 6 C IO捕获指令,与SIGABRT同义
SIGEMT 7,-,7
SIGSTKFLT -,16,- A 协处理器堆栈错误
SIGIO 23,29,22 A 某I/O操作现在可以进行了(4.2 BSD)
SIGCLD -,-,18 A 与SIGCHLD同义
SIGPWR 29,30,19 A 电源故障(System V)
SIGINFO 29,-,- A 与SIGPWR同义
SIGLOST -,-,- A 文件锁丢失
SIGWINCH 28,28,20 B 窗口大小改变(4.3 BSD, Sun)
SIGUNUSED -,31,- A 未使用的信号(will be SIGSYS)
(在这里,- 表示信号没有实现;有三个值给出的含义为,第一个值通常在Alpha和Sparc上有效,中间的值对应i386和ppc以及sh,最后一个值对应mips。信号29在Alpha上为SIGINFO / SIGPWR ,在Sparc上为SIGLOST。)
处理动作一项中的字母含义如下
A 缺省的动作是终止进程
B 缺省的动作是忽略此信号
C 缺省的动作是终止进程并进行内核映像转储(dump core)
D 缺省的动作是停止进程
E 信号不能被捕获
F 信号不能被忽略