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

    }

    运行结果:

  • 相关阅读:
    leetcode5 Longest Palindromic Substring
    leetcode17 Letter Combinations of a Phone Number
    leetcode13 Roman to Integer
    leetcode14 Longest Common Prefix
    leetcode20 Valid Parentheses
    leetcode392 Is Subsequence
    leetcode121 Best Time to Buy and Sell Stock
    leetcode198 House Robber
    leetcode746 Min Cost Climbing Stairs
    tomcat下使用druid配置jnid数据源
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/9117745.html
Copyright © 2011-2022 走看看