1、信号本质
信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。信号机制经过POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息。使用kill -l就会显示出linux支持的信号列表。其中列表中,编号为1 ~ 31的信号为传统UNIX支持的信号,是不可靠信号(非实时的),编号为32 ~ 63的信号是后来扩充的,称做可靠信号(实时信号)。不可靠信号和可靠信号的区别在于前者不支持排队,可能会造成信号丢失,而后者不会。注意事项:编号为0的信号量相当于一个PING 信号,用于检查进程是否存在。
2、信号来源
硬件:在终端按下按键;或硬件异常产生信号
软件:在终端调用kill命令;进程调用kill或sigqueue函数发送信号
3、进程对信号的响应
a>捕捉信号:对于要捕捉的信号,可以为其指定信号处理函数,信号发生时该函数自动被调用,在该函数内部实现对该信号的处理。
b>忽略信号:大多数信号都可使用这种方式进行处理,但是SIGKILL和SIGSTOP这两个信号不能被忽略,同时这两个信号也不能被捕获和阻塞。此外,如果忽略某某些由硬件异常产生的信号(如非法存储访问或除以0),则进程的行为是不可预测的。
c>按照系统默认方式处理。大部分信号的默认操作是终止进程,且所有的实时信号的默认动作都是终止进程。
4、各种信号的默认处理情况
程序不可捕获、阻塞或忽略的信号有:SIGKILL,SIGSTOP
不能恢复至默认动作的信号有:SIGILL,SIGTRAP
默认会导致进程流产的信号有:SIGABRT、SIGBUS、SIGFPE、SIGILL、SIGIOT、SIGQUIT、SIGSEGV、SIGTRAP、SIGXCPU、SIGXFSZ
默认会导致进程退出的信号有:SIGALRM、SIGHUP、SIGINT、SIGKILL、SIGPIPE、SIGPOLL、SIGPROF、SIGSYS、SIGTERM、SIGUSR1、SIGUSR2、SIGVTALRM
默认会导致进程停止的信号有:SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOU
默认进程忽略的信号有:SIGCHLD、SIGPWR、SIGURG、SIGWINCH
5、相关函数
代码段如下:
#include<signal.h>
typedef void(*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler); //signum表示所要处理的信号类型,handler描述信号关联动作
handler可取值为SIG_IGN(忽略该信号)、SIG_DFL(恢复对信号的系统默认处理)和sighandler_t类型的函数指针的三种方式,第三种方式需要在signal()被调用前申明一个上述的sighandler_t的函数,当接收到一个类型为sig的信号时,就会执行handler所指定的函数。
signal()会依参数signum 指定的信号编号来设置该信号的处理函数。当指定的信号到达时就会跳转到参数handler指定的函数执行。
当一个信号的信号处理函数执行时,如果进程又接收到了该信号,该信号会自动被储存而不会中断信号处理函数的执行,直到信号处理函数执行完毕再重新调用相应的处理函数。但是如果在信号处理函数执行时进程收到了其它类型的信号,该函数的执行就会被中断。
6、信号列表
在Linux系统中输入kill -l可以查询signal列表,对传统UNIX支持的信号进行梳理,见下:
1 SIGHUP 终端的挂断或进程死亡
2 SIGINT 来自键盘的中断信号(CTRL+C)
3 SIGQUIT 来自键盘的离开信号
4 SIGILL 非法指令
5 SIGTRAP 断点指令或其他trap指令产生
6 SIGABRT 来自abort的异常信号
7 SIGBUS 非法地址, 包括内存地址对齐(alignment)出错
8 SIGFPE 致命算术运算错误,如浮点、溢出等
9 SIGKILL 立即结束程序,本信号不能被阻塞、处理和忽略
10 SIGUSR1 留给用户使用
11 SIGSEGV 可能存在特定条件下的非法内存访问
12 SIGUSR2 留给用户使用
13 SIGPIPE 管道破裂:在读管道未打开或意外终止时往管道里写,写进程会收到此信号
14 SIGALRM 时钟定时信号,计算实际的时间或时钟时间
15 SIGTERM 程序结束信号,要求程序自己正常退出
16 SIGSTKFLT
17 SIGCHLD 子进程结束时,父进程会收到该信号
18 SIGCONT 让一个停止的(STOPPED)进程继续执行,本信号不能被阻塞
19 SIGSTOP 停止(STOPPED)进程的执行. 它和terminate以及interrupt的区别:该进程还未结束, 只是暂停执行. 本信号不能被阻塞, 处理或忽略.
20 SIGSTP 停止(STOPPED)进程的运行,但该信号可以被处理和忽略,来自键盘CTRL+Z
21 SIGTTIN 后台进程读终端
22 SIGTTOU 后台进程写终端
23 SIGURG out-of-band数据或“紧急”数据
24 SIGXCPU CPU时间超限
25 SIGXFSZ 文件资源大小超限
26 SIGVTALRM 虚拟时钟信号,计算该进程占用CPU的时间
27 SIGPROF 包括该进程用的CPU时间及系统调用时间(统计分布图用计时)
28 SIGWINCH 窗口大小改变
29 SIGIO 文件描述符准备就绪,可以开始进行输入/输出操作 ?
30 SIGPWR Power Failure
31 SIGSYS 非法系统调用
但注意,它与Linux系统中signum-generic.h中部分信号对应的值不同。注意区分
#ifndef _BITS_SIGNUM_GENERIC_H
#define _BITS_SIGNUM_GENERIC_H 1
#ifndef _SIGNAL_H
#error "Never include <bits/signum-generic.h> directly; use <signal.h> instead."
#endif
/* Fake signal functions. */
#define SIG_ERR ((__sighandler_t) -1) /* Error return. */
#define SIG_DFL ((__sighandler_t) 0) /* Default action. */
#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */
#ifdef __USE_XOPEN
# define SIG_HOLD ((__sighandler_t) 2) /* Add signal to hold mask. */
#endif
/* We define here all the signal names listed in POSIX (1003.1-2008);
as of 1003.1-2013, no additional signals have been added by POSIX.
We also define here signal names that historically exist in every
real-world POSIX variant (e.g. SIGWINCH).
Signals in the 1-15 range are defined with their historical numbers.
For other signals, we use the BSD numbers.
There are two unallocated signal numbers in the 1-31 range: 7 and 29.
Signal number 0 is reserved for use as kill(pid, 0), to test whether
a process exists without sending it a signal. */
/* ISO C99 signals. */
#define SIGINT 2 /* Interactive attention signal. */
#define SIGILL 4 /* Illegal instruction. */
#define SIGABRT 6 /* Abnormal termination. */
#define SIGFPE 8 /* Erroneous arithmetic operation. */
#define SIGSEGV 11 /* Invalid access to storage. */
#define SIGTERM 15 /* Termination request. */
/* Historical signals specified by POSIX. */
#define SIGHUP 1 /* Hangup. */
#define SIGQUIT 3 /* Quit. */
#define SIGTRAP 5 /* Trace/breakpoint trap. */
#define SIGKILL 9 /* Killed. */
#define SIGBUS 10 /* Bus error. */
#define SIGSYS 12 /* Bad system call. */
#define SIGPIPE 13 /* Broken pipe. */
#define SIGALRM 14 /* Alarm clock. */
/* New(er) POSIX signals (1003.1-2008, 1003.1-2013). */
#define SIGURG 16 /* Urgent data is available at a socket. */
#define SIGSTOP 17 /* Stop, unblockable. */
#define SIGTSTP 18 /* Keyboard stop. */
#define SIGCONT 19 /* Continue. */
#define SIGCHLD 20 /* Child terminated or stopped. */
#define SIGTTIN 21 /* Background read from control terminal. */
#define SIGTTOU 22 /* Background write to control terminal. */
#define SIGPOLL 23 /* Pollable event occurred (System V). */
#define SIGXCPU 24 /* CPU time limit exceeded. */
#define SIGXFSZ 25 /* File size limit exceeded. */
#define SIGVTALRM 26 /* Virtual timer expired. */
#define SIGPROF 27 /* Profiling timer expired. */
#define SIGUSR1 30 /* User-defined signal 1. */
#define SIGUSR2 31 /* User-defined signal 2. */
/* Nonstandard signals found in all modern POSIX systems
(including both BSD and Linux). */
#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */
/* Archaic names for compatibility. */
#define SIGIO SIGPOLL /* I/O now possible (4.2 BSD). */
#define SIGIOT SIGABRT /* IOT instruction, abort() on a PDP-11. */
#define SIGCLD SIGCHLD /* Old System V name */
/* Not all systems support real-time signals. bits/signum.h indicates
that they are supported by overriding __SIGRTMAX to a value greater
than __SIGRTMIN. These constants give the kernel-level hard limits,
but some real-time signals may be used internally by glibc. Do not
use these constants in application code; use SIGRTMIN and SIGRTMAX
(defined in signal.h) instead. */
#define __SIGRTMIN 32
#define __SIGRTMAX __SIGRTMIN
/* Biggest signal number + 1 (including real-time signals). */
#define _NSIG (__SIGRTMAX + 1)
#endif /* bits/signum-generic.h. */