实际执⾏行信号的处理动作称为信号递 达(Delivery),实际的处理方式有三种。
1、忽略带信号
2、默认处理动作
3、自定义处理动作
信号从产⽣生到递达之间的状态,称为信号未决(Pending)。
进程可以选择阻塞 (Block )某个信号。被阻塞的信号产⽣生时将保持在未决状态,直到进程解除对此信号的阻塞, 才 执⾏行递达的动作。
注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,⽽而忽略是在递 达之后 可选的⼀一种处理动作。信号在内核中的表⽰示可以看作是这样的:
每个信号都有两个标志位分别表⽰示阻塞(block)和未决(pending),还有⼀一个函数指针表⽰示处理 动作。信号产⽣生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标 志。
pengding信号集的数据结构是一张位图,
block信号机也是一张位图
普通信号时会被丢弃的,它只能记录一次
实时信号是可以被记录下来的
信号集和信号量集是不一样的。
pending表示当前进程的pending信号量集
block:表示当前进程的信号屏蔽字
修改pcb的pending表中的一个bit位->发信号
信号集操作函数
int sigemptyset(sigset_t *set);
//清零操作
int sigfillset(sigset_t *set);
//初始化set所指向的信号集,使其中所有信号的对 应bit置位,表⽰示 该信号集的有效信号包括系统⽀支持的所有信号
int sigaddset(sigset_t *set, int signo);
//在该信号集中添加有效信号
int sigdelset(sigset_t *set, int signo);
//在该信号集中删除某个有效信号
int sigismember(const sigset_t *set, int signo); //是⼀一个布尔 函数,⽤用于判断⼀一个信号集的有效信号中是否包含某种 信号,若包含则返回1,不包含则返回0, 出错返回-1。
sigprocmask
调⽤用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
返回值:若成功则为0,若出错则为-1 如果oset是⾮非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是⾮非空指 针,则 更改进程的信号屏蔽字,参数how指⽰示如何更改。如果oset和set都是⾮非空指针,则先 将原来的信号 屏蔽字备份到oset⾥里,然后根据set和how参数更改信号屏蔽字。假设当前的 信号屏蔽字为mask,下表说明了how参数的可选值。
sigpending
#include <signal.h>
int sigpending(sigset_t *set);
sigpending读取当前进程的未决信号集,通过set参数传出。调⽤用成功则返回0,出错则返回 -1
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void myhandler(int signal)
{
printf("get a signal:%d\n",signal);
exit(1);
}
void showpending(sigset_t *pending)
{
int i=1;
for(;i<=31;++i)
{
if(sigismember(pending,i))
{
printf("1");
}
else
{
printf("0");
}
}
printf("\n");
}
int main()
{
sigset_t s,p;
sigemptyset(&s);
sigemptyset(&p);
sigaddset(&s,SIGINT);
sigprocmask(SIG_BLOCK,&s,NULL);
sleep(3);
sigpending(&p);
showpending(&p);
signal(SIGQUIT,myhandler);
sleep(10);
sigprocmask(SIG_UNBLOCK,&s,NULL);
showpending(&p);
sigpending(&p);
return 0;
}