sigquit信号默认忽略吗_Linux信号:阻塞、未决、忽略

本文探讨了Linux系统中SIGQUIT信号的处理机制。当信号未被阻塞时,会执行默认操作。如果信号已被阻塞,即使设置为忽略,也会在解除阻塞后才可能被忽略。同时,介绍了SIG_BLOCK、SIG_UNBLOCK和SIG_SETMASK三种信号处理方式,以及SIGINT信号被阻塞时成为未决状态的例子。
摘要由CSDN通过智能技术生成

b4e1b2e1dda517c41872b73ba1e209ed.png

01 信号在内核中的表示 实际执行信号的处理动作称为信号递达(Delivery); 信号从产生到递达之间的状态,称为信号未决(Pending); 进程可以选择阻塞(Block)某个信号,SIGKILL 和 SIGSTOP 不能被阻塞; 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。 注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。 每个信号都有两个标志位分别表示阻塞和未决,还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。
  • 信号未阻塞也未产生过,当它递达时执行默认处理动作。

  • 信号已经产生,但正在被阻塞,所以暂时不能递达。即使它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。

  • 信号虽然还没有产生,但是已经被设置为阻塞状态,一旦产生将被阻塞。

02 信号集处理函数 初始化信号集为空:
int sigemptyset(sigset_t *set);
把信号添加到信号集:
int sigaddset(sigset_t *set, int signum);
把信号集更新到进程控制块中:
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
how参数含义:
  • SIG_BLOCK:把信号集中的信号设置为阻塞状态;

  • SIG_UNBLOCK:把信号集中的信号设置为非阻塞状态;

  • SIG_SETMASK:信号状态设置为 set 指向的值。

获取当前进程的未决信号:
int sigpending(sigset_t *set);
判断信号是不是未决状态:
int sigismember(const sigset_t *set, int signum);
03 阻塞和忽略 阻塞示例代码:
#include #include #include #include #include #include #include #include void printsigset(const sigset_t *p_set){    int i = 0;    //遍历64个信号,    for (; i < 64; i++)    {        //信号从1开始   判断哪些信号在信号未决状态字中        if (sigismember(p_set, i + 1))            putchar('1');        else            putchar('0');    }    printf("\n");}void catch_signal(int sign){    switch (sign)    {        case SIGINT:            printf("accept SIGINT!\n");            exit(0);            break;        case SIGQUIT:            printf("accept SIGQUIT!\n");            //收到SIGQUIT,取消SIGINT的阻塞状态            sigset_t uset;            sigemptyset(&uset);            sigaddset(&uset,SIGINT);            //将信号集uset更新到进程控制块PCB结构中,取消阻塞信号SIGINT            sigprocmask(SIG_UNBLOCK,&uset,NULL);            break;    }}int main(){    //定义未决信号集(pending)、阻塞信号集    sigset_t p_set, b_set;    //清空信号集    sigemptyset(&b_set);    //将信号SIGINT加入到信号集中    sigaddset(&b_set, SIGINT);    //注册信号    if (signal(SIGINT, catch_signal) == SIG_ERR)    {        perror("signal error");        return -1;    }    if (signal(SIGQUIT, catch_signal) == SIG_ERR)    {        perror("signal error");        return -1;    }    //将信号集b_set更新到进程控制块PCB结构中,阻塞信号SIGINT(即使用户按下ctrl+c,信号也不会递达)    sigprocmask(SIG_BLOCK, &b_set, NULL);    while (1)    {        /*         * 获取当前信号未决信息,即使在sigprocmask()函数中设置了信号阻塞,         * 但是如果没有信号的到来,信号未决状态字对应位依然是0         * 只要有信号到来,并且被阻塞了,信号未决状态字对应位才会是1         * */        sigpending(&p_set);        //打印信号未决信息        printsigset(&p_set);        sleep(1);    }    return 0;}
运行结果如下:

0e242d43932c473440cd0424ad9cdfe4.png

虽然 SIGINT 被设置为阻塞,但是进程还没有收到 SIGINT 信号,所以不存在未决信号。 按下 CTRL + C,结果如下:

c8df874ac4a3acf6614cab6d003168f9.png

进程收到 SIGINT 信号,由于 SIGINT 被设置为阻塞状态,所以不能递达,成了未决状态。

按下 CTRL + \,即发送 SIGQUIT 信号:

20fd7fac5cab2c688dc54af5898af698.png

进程收到 SIGQUIT 信号,执行 catch_signal 信号处理函数,取消了 SIGINT 的阻塞属性。由于 SIGINT 处于未决状态,被取消阻塞后,继续执行信号处理函数,退出进程。 信号阻塞可以理解成,发出了信号,但是拦住他,此时就处于未决状态;松开他,信号还会继续发送抵达进程。 忽略示例代码:
#include int main(){    signal(SIGINT, SIG_IGN);    while (1);    return 0;}
这个就很好理解了,运行的时候,无论怎么按 CTRL + C,代码都不会停止。 信号阻塞和信号忽略的区别:阻塞是发出了信号,但是信号没有递达,所以进程没有响应;忽略是发出了信号,进程收到了信号,采取的动作是忽略。

d0162280f0f996e348a937210701d58d.png

PS.春招已经如此艰难,备战秋招,刻不容缓。智能硬件VIP培训班,3个月教学+1个月项目实战。有需要得同学扫码咨询!

f25e4c706d0c1bef763c737c95bce2cd.png

dbfa92a85b6412accadbc078e2e9cbe3.png

453661357c0b72c47400d7124dd39131.png

d06f7be74353d0b660211b3bdf70831b.png

a2aed06e7cdb89d1f9f8d95f08545230.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值