信号的概念
信号是软件层上对中断的一种模拟,又称为软件中断(软中断)。
信号和中断的相同和区别
信号和中断都是异步通信方式。
信号没有优先级,中断有优先级;信号处理程序是在用户态(软件层),中断处理是在内核态;信号处理有延迟,中断处理及时。(由于信号处理是在软件层面上实现的,其实现手段导致信号有很长的延迟性,但对用户来说不易察觉)
内核对信号的处理
可以告诉内核在信号出现时按以下3种方式之一进行处理:
(1)忽略信号(SIGKILL和SIGSTOP不能被忽略,因为这两个信号是 内核 和 root 用来管理进程的)
(2)捕捉信号(SIGKILL和SIGSTOP不能被捕捉)
(3)默认处理(执行系统默认动作,man 7 signal可以查看)
查看信号
kill -l查看所有信号。
1-31是Unix继承过来的,是不可靠信号,非实时信号,不支持排队,可能会造成信号丢失。
34-64是优化后的,可靠信号,实时信号,支持排队,不会丢失信号。
信号的产生
(1)按键产生
ctrl+c 2) SIGINT
ctrl+z 20)SIGTSTP(停止/暂停)
ctrl+\ 3)SIGQUIT(退出)
(2)硬件异常产生
除0操作 8)SIGFPE
非法访问内存 11)SIGSEGV(段错误)
总线错误 7)SIGBUS
(3)函数产生
int kill(pid_t pid, int sig);
int raise(int signal);
void abort(void);
unsigned int alarm(unsigned int seconds);
setitimer
信号的控制
一个block/pending/handler占8字节,一共64bit,每个信号占一位。可以通过设置block来对信号进行屏蔽。
block信号阻塞,例如sigint为1时,阻塞sigint信号,可以通过信号集操作函数进行操作,如果是实时信号(可靠信号),则被阻塞的信号会排队(直到达到队列上线,多余的信号丢掉),如果是非实时信号(不可靠信号)则只会保留一个信号,等恢复不阻塞状态时,继续发送信号,实时信号会受到多个信号,而非实时信号只有一个。
pending信号未决,例如sigint为1表示收到sigint信号但是没有送达。block设置为1时有发送信号则pending变为1。不能设置,只读。当pangding为1时表示有信号被阻塞了,当恢复不阻塞时,继续传送信号。
handler信号处理方式,默认处理方式或者自己捕捉信号处理。
信号集操作函数
①、int sigemptyset(sigset_t *set);
作用:将某个block集(信号集)清0
②、 int sigfillset(sigset_t *set);
作用:将某位信号集置1
③、int sigaddset(sigset_t *set, int signum);
作用:将某个信号加入信号集
④、 int sigdelset(sigset_t *set, int signum);
作用: 将某个信号清出信号集
⑤、int sigismember(const sigset_t *set, int signum);
作用:判断某个信号是否在信号集中
上面五个函数用于处理sigset_t类型的信号集,当规划好信号集后,需要用sigprocmask函数将信号集应用到pcb(Processing Control Block)中。具体如下:
int sigprocmask(int how, const sigset_t * set, sigset_t * oldset);
关于how选项:
(1)SIG_BLOCK 将set中的信号加入阻塞(block),与block进行或操作
(2)SIG_UNBLOCK 将set中的信号移出阻塞,block设为0
(3)SIG_SETMASK 将block设为set
如果how被忽略,而oldset不为空,则将block的值返回到oldset中。
未决信号集
sigpending函数
信号捕捉函数
signal函数
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
signal函数有两个函数,一个是int类型的signal,一个是sighandler_t类型的函数指针。返回值也是sighandler_t类型。
sighandler_t的一个参数int,传入的signal。
sigaction函数
int sigaction(int signum, const struct sigaction *act, struct sigaction* oldact);
可以在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);
};