zoukankan      html  css  js  c++  java
  • linux c编程:信号(三) sigprocmask和sigpending函数

    信号源为目标进程产生了一个信号,然后由内核来决定是否要将该信号传递给目标进程。从信号产生到传递给目标进程的流程图如下图所示:

    进程可以阻塞信号的传递。当信号源为目标进程产生了一个信号之后,内核会执行依次执行下面操作,

    1. 如果目标进程设置了忽略该信号,则内核直接将该信号丢弃。

    2. 如果目标进程没有阻塞该信号,则内核将该信号传递给目标进程,由目标进程执行相对应操作。

    3. 如果目标进程设置阻塞该信号,则内核将该信号放到目标进程的阻塞信号列表中,等待目标进程对该类型信号的下一步设置。若目标进程后续设置忽略该信号,则内核将该信号从目标进程的阻塞信号列表中移除并丢弃。若目标进程对该信号解除了阻塞,内核将该信号传递给目标进程进行相对应的操作。

    在信号产生到信号传递给目标进程之间的时间间隔内,我们称该信号为未决的(pending)

    每个进程都有一个信号屏蔽字(signal mask),它规定了当前要阻塞传递给该进程的信号集。对于每种可能的信号,信号屏蔽字中都有一位与之对应。

    信号集:

    函数 sigemptyset 初始化由 set 指向的信号集,清除其中所有信号。

    1 int sigemptyset(sigset_t *set);

    返回值:若成功则返回0,若出错则返回-1函数 sigfillset 初始化由 set 指向的信号集,使其包含所有信号。

    2 int sigfillset(sigset_t *set);
    返回值:若成功则返回0,若出错则返回-1

    函数 sigaddset 将一个信号 signo 添加到现有信号集 set 中。

    3 int sigaddset(sigset_t *set, int signo);
    返回值:若成功则返回0,若出错则返回-1

    函数 sigdelset 将一个信号 signo 从信号集 set 中删除。

    4 int sigdelset(sigset_t *set, int signo);
    返回值:若成功则返回0,若出错则返回-1

    函数 sigismember 判断指定信号 signo 是否在信号集 set 中。

    5 int sigismember(const sigset_t *set, int signo);
    返回值:若真则返回1,若假则返回0,若出错则返回-1

     

    函数sigprocmask

    调用 sigprocmask 函数可以检测或者设置进程的信号屏蔽字。

    #include <signal.h>
    int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
    返回值:若成功则返回0,若出错则返回-1

    若 oset 参数是一个非空指针,则进程的当前信号屏蔽字将通过 oset 返回。若 set 参数是一个非空指针,则参数 how 将指示如何修改当前信号屏蔽字。how 的可选值如下表所示:

    how

    说明

    SIG_BLOCK

    该进程新的信号屏蔽字是其当前信号屏蔽字和 set 指向信号集的并集。

    SIG_UNBLOCK

    该进程的信号屏蔽字是当前信号屏蔽字和 set 所指向信号集补给的交集。set 包含了我们希望解除阻塞的信号。

    SIG_SETMASK

    该进程新的信号屏蔽字设置为 set 所指向的信号集。

    下面来看个具体的使用例子

    void sig_alarm(int signo){

        printf("received SIGALRM ");

        return;

    }

    void signal_set_fun(){

        sigset_t sigset;

        sigemptyset(&sigset);

        sigaddset(&sigset,SIGALRM);

        if(sigprocmask(SIG_BLOCK,&sigset,NULL)<0){

            printf("sigprocmask error: ");

        }

        if(signal(SIGALRM,sig_alarm) < 0){

            printf("signal error: ");

        }

        alarm(2);

        sleep(4);

        printf("before unblock sigprocmask ");

        if(sigprocmask(SIG_UNBLOCK,&sigset,NULL)<0){

            printf("sigprocmask unblock error: ");

        }

    }

    在上面的程序文件中先调用 sigprocmask 设置阻塞信号 SIGALRM,然后调用 alarm(2) 设置一个两秒钟的闹钟(两秒钟之后将向当前进程产生一个 SIGALRM 信号)。在睡眠 4 秒钟之后(此时应该已经产生了 SIGALRM 信号),调用 sigprocmask 函数解除对信号SIGALRM 的阻塞。

    运行结果如下:

    函数sigpending

    函数 sigpending 获取当前进程所有未决的信号。通过其 set 参数返回未决的信号集。

    #include <signal.h>
    int sigpending(sigset_t *set);
    返回值:若成功则返回0,若出错则返回-1

    来看一个实际使用的例子:

    void alarm_is_pending(char *str){

        sigset_t pendingsig;

        printf("%s: ",str);

        if(sigpending(&pendingsig) < 0){

            printf("sigpending required error: ");

        }

        if(sigismember(&pendingsig,SIGALRM)){

            printf("SIGALRM is pending ");

        }

        else{

            printf("SIGALRM is not pending ");

        }

    }

     

    void signal_pending_fun(){

        sigset_t sigset;

        sigemptyset(&sigset);

        sigaddset(&sigset,SIGALRM);

        if(sigprocmask(SIG_BLOCK,&sigset,NULL) < 0){

            printf("sigprocmask error: ");

        }

        alarm_is_pending("before alarm");

        alarm(2);

        sleep(4);

        alarm_is_pending("after alarm");

        exit(0);

    }

    运行结果:

  • 相关阅读:
    排序算法比较
    直接选择排序
    静态查找表和动态查找表
    memset函数
    二叉树
    使用vue+Element的Upload+formData实现图片传到SpringBoot,再上传到fastdfs
    vue中的export与export default的区别
    人人开源
    SpringBoot注解
    大厂薪资
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/9117745.html
Copyright © 2011-2022 走看看