十七、Linux系统编程-信号(四)信号在内核中表示、信号的阻塞和未决

时间:2023-02-03 14:43:14
一、信号在内核中的表示         执行信号的处理动作称为信号递达Delivery),信号从产生到递达之间的状态,称为信号未决Pending)。进程可以选择阻塞(Block)某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。信号在内核中的表示如下: 十七、Linux系统编程-信号(四)信号在内核中表示、信号的阻塞和未决

二、信号阻塞与未诀
三、信号集操作函数 (1)、信号集 函数声明:
#include <signal.h>
int sigemptyset(sigset_t *set);//全部置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);//是否为1
函数参数:信号集,信号代码
返回值:成功返回0,失败返回-1
(2)、读取或更改进程的信号屏蔽字 函数声明:
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
函数参数:改变方式,信号集,原来的信号集
返回值:成功返回0,失败返回-1并设置errno
 如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。如果osetset都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据sethow参数更改信号屏蔽字。

示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0)
void handle(int sig);
void printsigset(sigset_t* set)
{
int i;
for (i=1;i < 64; ++i)
{
if (sigismember(set,i))
putchar('1');
else
putchar('0');
}
printf("\n");
}
int main(int argc,char* argv[])
{
sigset_t pset;
sigset_t bset;
sigemptyset(&bset);
sigaddset(&bset,SIGINT);
if (signal(SIGINT,handle) == SIG_ERR)
ERR_EXIT("signal error");
if (signal(SIGQUIT,handle) == SIG_ERR)
ERR_EXIT("signal error");
sigprocmask(SIG_BLOCK,&bset,NULL);
for(;;)
{
sigpending(&pset);
printsigset(&pset);
sleep(1);
}
return 0;
}

void handle(int sig)
{
printf("recv a sig=%d\n",sig);
if (sig == SIGQUIT)
{
sigset_t uset;
sigemptyset(&uset);
sigaddset(&uset,SIGINT);
sigprocmask(SIG_UNBLOCK,&uset,NULL);
}
}