一、信号的基本概念
1. 什么是信号
信号是Linux系统为了响应某种状况而产生的事件。进程收到信号后应该采取相应的动作。
信号机制是进程之间相互传递消息的一种方法,信号全称为软中断信号,也有人称作软中断。从它的命名可以看出,它的实质和使用很象中断。所以,信号可以说是进程控制的一部分
2. 哪些情况会产生信号?
- 键盘事件
- 非法内存
- 硬件故障
- 环境切换
3. 如何查看信号
- 查看系统中的信号:
kill -l
; - 查看信号的默认处理:
man 7 signal
; - 有的信号有多个值,对应不同系统(中间那个值对应Linux系统)
4. 进程收到信号的三种处理方式:
- 默认:执⾏行该信号的默认处理动作。
- 忽略:信号来了不处理,相当于丢掉信号(
SIGKILL
和SIGSTOP
不能被忽略) - 捕获并处理:提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个函数(
SIGKILL
和SIGSTOP
不能被捕获)。
5. 信号的分类
- 不可靠信号 (1-31号信号不可靠)
Linux的信号继承自早期的UNIX信号,UNIX信号有一定的缺陷:
1. 信号处理函数执行完毕,信号恢复成默认处理方式(Linux已改进)
2. 会出现信号丢失,信号不排队
可靠信号(34-64号信号可靠)
不会出现信号丢失,支持排队,信号处理函数执行完后不会恢复成缺省处理方式。实时信号:就是可靠信号
- 非实时信号:就是不可靠信号
可靠信号和不可靠信号的区别:
这里的不可靠主要是不支持信号队列,就是当多个信号发生在进程中的时候(收到信号的速度超过进程处理的速度的时候),这些没来的及处理的信号就会被丢掉,仅仅留下一个信号。
可靠信号是多个信号发送到进程的时候(收到信号的速度超过进程处理信号的速度的时候),这些没来的及处理的信号就会排入进程的队列。等进程有机会来处理的时候,依次再处理,信号不丢失。
二、操作信号
1. 注册信号 —— signal()函数
注册信号实际是对信号进行三种处理操作,用于告诉当前进程接收信号后该去执行什么动作。
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
函数功能:开始获取信号值为signum的信号,如果获取到该信号,则开始执行handler指向的函数。
第一个参数signum
:指明了所要处理的信号类型,它可以取除了SIGKILL
和SIGSTOP
外的任何一种信号。
第二个参数handler
:描述了与信号关联的动作,它可以取以下三种值:
SIG_IGN
:表示忽略该信号。#define SIG_IGN ((sighandler_t)1)
SIG_DFL
:表示恢复对信号的系统默认处理。不写此处理函数默认也是执行系统默认操作。#define SIG_IGN ((sighandler_t)0)
sighandler_t
类型的函数指针:执行自己写的代码。
返回值:
成功返回原本的信号处理函数指针;
失败返回SIGERR
; SIGERR
的宏为 #define SIG_IGN ((sighandler_t)-1)
代码示例:
#include <signal.h>
#include <stdio.h>
#include <s