之前的linux学习里,介绍了信号相关内容,这里记录一些重点内容
1. 不可靠信号
不可靠信号值的是,信号有可能会丢失。
但在早期的uinx系统中存在这样一种情况:进程每次接收到信号时,随即将该信号动作复位为默认值。
2. 中断的系统调用
将系统调用分为两种:
低速系统调用和其他系统调用,低速系统调用是可能会使进程永远阻塞的一类系统调用,它们包括:
- 在读某些文件时,如果数据不存在,那么可能使调用者永远阻塞。
- 在写这些类型的文件时,如果不能立即接受这些数据,则也可能使调用者永远阻塞。
- 打开这些文件时,在某种条件发生之前也可能使调用者永远阻塞。
- pasue和wait函数
- 某些ioctl函数
- 某些进程间通信函数
3. 可重入与不可重入
进程捕捉到信号并对其进行处理时,进程正在执行的指令序列就被信号处理程序临时中断,它首先执行该信号处理程序中的指令。如果从信号处理程序返回,则继续执行在捕捉信号时进程正在执行的正常指令序列,但是在信号处理程序中,不能判断捕捉到信号时进程在何处执行,例如正好,malloc函数在分配空间,这就会对进程造成破坏,所以就分了可重入的函数和不可重入的函数,如果信号处理程序调用u不可重入函数,这是未知的错误。
一般情况下,有下面情况的函数,大概率是不可重入的:
- 使用静态数据结构
- 调用malloc和free
- 标准IO函数
4. 未决信号
当引发信号的事件发生时,为进程产生了一个信号,这个事件可以是硬件异常,kill函数调用,终端产生的信号,当对信号采取了这种动作时,我们说向进程递送了一个信号,在产生与递送这个阶段,我们称信号是未决的。
进程可选用信号递送阻塞。如果为进程产生了一个阻塞的信号,而且对信号的动作是系统默认动作,或捕捉该信号,则称该进程将此信号保持为未决状态。
5. kill和raise函数
先来看两个函数的原型:
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
int raise(int sig);
区别:kill函数将信号发送给进程或者进程组,raise函数则允许进程向自身发送信号。调用rasie(sig)等价于kill(getpid(),sig)。
注意kill的pid参数:
- pid>0, 将该信号发送给进程ID为pid的进程。
- pid==0,将该信号发送给发送进程属于同一进程组的所有进程。
- pid<0, 将信号发送给进程组ID等于pid的绝对值。
- pid==-1,将信号发送给发送进程有权限向它们发送信号的系统上的所有进程。
6. 信号集
信号集处理函数:
#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
- sigemptyset的作用是初始化给的那个set,清除其中所有信号。
- sigfillset作用是初始化给的那个的set,使其包含所有信息。
- sidadd/delset两个分别是添加/删除一个信号。
- sigismenber作用是测试一个引号是否信号集的。