信号(阻塞未达 信号集)

信号的阻塞未达

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

PCB进程控制块中函数有信号屏蔽状态字(block)信号未决状态字(pending)还有是否忽略标志。

信号屏蔽状态字(block),1代表阻塞、0代表不阻塞;信号未决状态字(pending)的1代表未决,0代表信号可以抵达了。

向进程发送SIGINT,内核首先判断信号屏蔽状态字是否阻塞,信号未决状态字(pending相应位制成1;若阻塞解除,信号未决状态字(pending)相应位制成0;表示信号可以抵达了。

block状态字、pending状态字 64bit。

block状态字用户可以读写,pending状态字用户只能读;这是信号的设计机制。

信号集

 #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);

用sigprocmask函数更改进程的信号屏蔽状态

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

如果oldset是非空指针,则读取进程的当前信号屏蔽字通过oldset参数传出。如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。如果oldset和set都是非空指针,则先将原来的信号屏蔽字备份到oldset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下图说明了how参数的可选值


用sigpending函数获取信号未决状态字信息

#include <signal.h>
int sigpending(sigset_t *set);

案例演示

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<stdlib.h>
void usr(int signo)
{
    if(signo==SIGINT)
    {
        printf("SIGINT signal called!\n");
    }
}
void printsetstatus(sigset_t *pset)
{
    int i;
    for(i=1; i<=64; i++)
    {
        if(sigismember(pset,i))
        {
            printf("signal status %d is member\n",i);
        }

    }
}
int main(int argc,char *argv[])
{
    sigset_t pset,bset;
    sigemptyset(&bset);
    sigaddset(&bset,SIGINT);
    if(signal(SIGINT,usr)==SIG_ERR)
    {
        printf("error!\n");
    }
    sigprocmask(SIG_BLOCK,&bset,NULL);
    for(;;)
    {
        sigpending(&pset);
        printsetstatus(&pset);
        sleep(1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_33506160/article/details/80347760
今日推荐