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

时间:2022-11-05 14:45:52
一、信号在内核 中的表示
        执行信号的处理动作称为信号递达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);
        }
}