1. 信号的初步认识
1.1 信号的特点
信号所携带的信息量少,操作简单
1.2 信号的状态
1.产生
①由键盘产生:例如Ctrl+c,Ctrl+
②命令:kill
③系统函数:kil
④软条件:定时器
⑤硬件:段错误,除0错误
由键盘和和硬件产生的信号统称为硬件方式,其余的为软件方式
2.未决状态
处在该状态的信号没有被处理。
3.递达状态
信号被处理。处理信号的方式如下:
- 忽略
- 捕捉
- 执行了默认动作
信号是由内核发送的,优先级比较高。进程收到信号后,会暂停正在处理的事情,优先处理信号,处理完成之后继续原来的工作
1.3 处理方式
1.忽略信号,这是大多程序对信号的处理方式,但SIGKILL和SIGSTOP信号不能被忽略。这是为了最后能够有一种方式结束掉进程
2.捕捉信号,捕捉信号后可以做相应的一些处理
3.执行默认动作,大多数信号的默认动作为终止进程
1.4 产看信号
使用 kill -l 命令可以查看信号
2. 信号集
2.1 信号集的相关概念
1.未决信号集:没有被当前进程处理的信号
2.阻塞信号集:将某个信号放到阻塞信号集,这个信号就不会被进程处理,阻塞解除之后,信号被处理。
信号产生后,处于未决状态,进程受到信号后信号会被放入未决信号集中。在未决信号集中的信号等待被处理,进程会判断阻塞信号集中信号对应的标志位是否为1,如果为1不处理该信号,如果为0处理该信号
3.自定义信号集:用户可以使用自定义信号集对信号集进行操作。
相关处理函数如下:
- 将set集合置空
int sigemptyset(sigset_t *set);
- 将所有信号加入set集合
int sigfillset(sigset_t *set);
- 将signo信号加入到set集合
int sigaddset(sigset_t, *set, int signo);
- 从信号集中移除signo信号
int sigdelset(sigset_t *set, int signo);
- 判断信号是否存在
int sigismember(const sigset_t *set, int signo);
- 检测信号集是否为空
int sigisemptyset(const sigset_t *set);
- 按逻辑与方式将两个信号集并
int sigandset(sigset_t *set, const sigset_t *left, const sigset_t *right);
*按逻辑或方式将两个信号集并
int sigorset(sigset_t *set, const sigset_t *left, const sigset_t *right);
sigprocmask函数
- 屏蔽按到接触信号屏蔽,将自定义信号集设置给阻塞信号集
- 函数原型:
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
信号的捕捉
1.signal函数
typedef void (*sighandler_t)(int);
sighandler_t signal(
int signum, //要捕捉的信号
sighandler_t handler //执行的动作
);
handler是一个函数指针,函数指向的类型为*sighandler_t,即它指向的函数有一个int型参数,返回类型为void
如果handler不是函数指针,就必须设置为SIG_IN(忽略该信号),SIG_DFL(执行默认动作)
2.sigaction函数:可以读取和修改与指定信号相关联的处理动作。
int sigaction(
int signum, //捕捉的信号
construction struct sigaction *act, //信号的处理函数
struct sigaction *oldact //旧的信号处理函数被存储在这
);
/*sigaction结构体*/
struct sigaction {
void (*sa_handler)(int); //信号的处理方式
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask; //在信号处理函数执行过程中,临时屏蔽指定的信号,额外屏蔽
int sa_flags; //通常设置为0
void (*sa_restorer)(void); //不再使用
};
处理方式:
- 若act为非空,则根据act结构体中的信号处理方式处理信号
- 若oldatc为非空,则根据原来的信号处理函数处理信号,根据act中的设置处理动作
- handler 的设置与上述signal的相同,如果handler不是函数指针,就必须设置为SIG_IN(忽略该信号),SIG_DFL(执行默认动作)
内核实现信号的捕捉
- 用户注册一个信号处理函数sighandler。
- 正在运行的程序,遇到中断、异常或是系统调用时进入内核态。
- 内核在处理完异常返回主函数之前,会检查有无信号未处理。检查到有信号未处理,并按照用户自定义的函数处理,如果没有自定义函数,则按照默认动作处理。
- 若设置了自定义处理函数,内核返回用户态执行sighandler函数
- 执行完sighandler函数后,执行系统调用sigreturn回到内核态
- 检查是否还有信号需要处理,如果没有就返回主程序继续主程序