信号是进程间通信机制中唯一的异步通信机制,在实现上是一种软中断,信号可以导致一个正在运行的进程被中断,进而处理一个突发事件。
目录
一、信号表
二、信号术语
三、信号使用
1、信号安装
(1)signal()
(2)sigaction()
2、信号发送
(1)kill函数
(2)raise函数
(3)alarm函数
(4)abort函数
(5)pause函数
(6)sigqueue函数
3、信号集操作函数
4、信号阻塞函数
四、注意事项
Linux在/usr/include/asm-generic/signal.h中详细定义了信号的信号值,其内容如下:
取值 | 名称 | 解释 | 默认动作 |
---|---|---|---|
1 | SIGHUP | 挂起 | |
2 | SIGINT | 中断 | |
3 | SIGQUIT | 退出 | |
4 | SIGILL | 非法指令 | |
5 | SIGTRAP | 断点或陷阱指令 | |
6 | SIGABRT | abort发出的信号 | |
7 | SIGBUS | 非法内存访问 | |
8 | SIGFPE | 浮点异常 | |
9 | SIGKILL | kill信号 | 不能被忽略、处理和阻塞 |
10 | SIGUSR1 | 用户信号1 | |
11 | SIGSEGV | 无效内存访问 | |
12 | SIGUSR2 | 用户信号2 | |
13 | SIGPIPE | 管道破损,没有读端的管道写数据 | |
14 | SIGALRM | alarm发出的信号 | |
15 | SIGTERM | 终止信号 | |
16 | SIGSTKFLT | 栈溢出 | |
17 | SIGCHLD | 子进程退出 | 默认忽略 |
18 | SIGCONT | 进程继续 | |
19 | SIGSTOP | 进程停止 | 不能被忽略、处理和阻塞 |
20 | SIGTSTP | 进程停止 | |
21 | SIGTTIN | 进程停止,后台进程从终端读数据时 | |
22 | SIGTTOU | 进程停止,后台进程想终端写数据时 | |
23 | SIGURG | I/O有紧急数据到达当前进程 | 默认忽略 |
24 | SIGXCPU | 进程的CPU时间片到期 | |
25 | SIGXFSZ | 文件大小的超出上限 | |
26 | SIGVTALRM | 虚拟时钟超时 | |
27 | SIGPROF | profile时钟超时 | |
28 | SIGWINCH | 窗口大小改变 | 默认忽略 |
29 | SIGIO | I/O相关 | |
30 | SIGPWR | 关机 | 默认忽略 |
31 | SIGSYS | 系统调用异常 |
也可以使用kill -l
来查看信号的名字以及序号:
进程处理某个信号前,需要先在进程中安装此信号。安装过程主要是建立信号值和进程对相应信息值的动作。信号安装函数有两个:
#include
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
函数参数:
signum:指定信号的值
handler:指定针对该信号值的处理,有以下选项可供选择:
- SIG_IGN:忽略该信号
- SIG_DFL:系统默认方式处理信号
- 函数指针:自定义处理
返回值:
成功则返回handler值,失败则返回SIG_ERR
#include
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
函数参数:
signum:指定信号的值
act:设置对signum信号的新处理方式,,为NULL,则表示使用默认方式进行处理。struct sigaction结构体内容为:
struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); }
- _sa_handler:同signal()的参数handler,代表新的信号处理函数
- _sa_sigaction:新的信号安装机制,处理函数被调用的时候,不但可以得到信号编号,而且可以获悉被调用的原因以及产生问题的上下文的相关信息。。第一个参数为信号值,第三个参数没有使用,第二个参数是指向siginfo_t结构的指针,结构中包含信号携带的数据值。
- sa_mask:用来设置在处理该信号时,暂时将sa_mask 指定的信号集搁置
- sa_flags:用来设置信号处理的其他相关操作,下列的数值可用:
- SA_RESTART:使被信号打断的系统调用自动重新发起。
- SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
- SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程。
- SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
- SA_RESETHAND:信号处理之后重新设置为默认的处理方式。
- SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数。
oldact:用以存储原来对信号的处理方式,不关心则设置为NULL
返回值:
成功返回0,失败返回-1
向指定进程发送指定信号
#include
#include
int kill(pid_t pid, int sig);
函数参数:
pid:要发送的目标进程ID:
- pid > 0:将发送个该 pid 的进程
- pid == 0:将会把信号发送给与发送进程属于同一进程组的所有进程,并且发送进程具有权限想这些进程发送信号。
- pid < 0:将信号发送给进程组ID 为 pid 的绝对值得,并且发送进程具有权限向其发送信号的所有进程
- pid == -1:将该信号发送给发送进程的有权限向他发送信号的所有进程。(不包括系统进程集中的进程)
sig:发送的信号编号值
返回值:
成功则返回0,失败则返回SIG_ERR
向自身发送指定信号。
#include
#include
int raise(int signo);
函数参数:
sigo:发送的信号编号值
返回值:
成功则返回0,失败则返回SIG_ERR
指定内核为调用进程在指定的seconds秒后发出一个SIGALRM的信号
#include
#include
unsigned int alarm(unsigned int seconds);
__useconds_t ualarm(__useconds_t value,__useconds_t interval);
函数参数:
seconds:指定的seconds秒后发出一个SIGALRM的信号:
- seconds=0:取消之前的设置
- seconds>0:seconds秒后发出一个SIGALRM的信号
value:指定函数将在value 微妙内产生SIGALARM信号
interval:指定在之后每interval微妙时,再次产生SIGALARM信号
返回值:
函数第一次调用时,执行成功返回0,失败返回-1。
若之前已有调用,再次调用函数则表示重置时间间隔,执行成功则返回距上次信号发送,剩余间隔时间。
向自身发送SIGABORT信号,默认情况下进程会异常退出,当然可定义自己的信号处理函数。即使SIGABORT被进程设置为阻塞信号,调用abort()后,SIGABORT仍然能被进程接收。
#include
void abort(void);
使进程挂起,直到捕捉到一个信号为止
#include
int pause(void);
主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用
#include
#include
int sigqueue(pid_t pid, int sig, const union sigval val);
函数参数:
pid:指定接收信号的进程id
sig:发送的信号值
val:信号的附加参数,联合体union sigval为:
typedef union sigval { int sival_int; void *sival_ptr; }sigval_t;
返回值:
成功则返回0,失败则返回-1
/*清空set代表的信号集*/
int sigemptyset(sigset_t* set)
/*添加信号sig到信号集set中*/
int sigaddset(sigset_t* set,int sig);
/*从信号集set中删除信号sig*/
int sigdelset(sigset_t* set,int sig);
/*检测信号sig是否在信号集set中*/
int sigismember(sigset_t* set,int sig);
/*检测信号集set是否为空信号集*/
int sigisemptyset(sigset_t* set);
/*将信号集left与信号集right按照逻辑与的方式合并到信号集set中*/
int sigandset(sigset_t* set,sigset_t* left,sigset_t* right);
/*将信号集left与信号集right按照逻辑或的方式合并到信号集set中*/
int sigandset(sigset_t* set,sigset_t* left,sigset_t* right);
// 不同how参数,实现不同功能:
// SIG_BLOCK:将set指向信号集中的信号,添加到进程阻塞信号集;
// SIG_UNBLOCK:将set指向信号集中的信号,从进程阻塞信号集删除;
// SIG_SETMASK:将set指向信号集中的信号,设置成进程阻塞信号集;
sigprocmask(int how, const sigset_t *set, sigset_t *oldset));
// 获取已发送到进程,却被阻塞的所有信号
sigpending(sigset_t *set));
// 用mask代替进程的原有掩码,并暂停进程执行,直到收到信号再恢复原有掩码并继续执行进程。
sigsuspend(const sigset_t *mask));
信号处理函数必须保证其可重入性