• 信号集函数


    POSIX信号集操作

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

    sigset_t 是信号集类型。信号集实际上就是一个位图,每个信号表示对应位。

    顾名思义:

    • "empty":清空信号集的每一位(置0)。
    • "fill": 填充信号集的每一位(置1)。
    • "add": 加入一个信号到信号集中(置1)。
    • "del": 从信号集中移除一个信号(置0)。
    • "ismember:" 判断是否在信号集中。

    参数解释

    • set: 我们所操作的信号集。
    • **signum: ** 操作的信号。

    返回值

    • sigismember返回值:
      • 在信号集内返回1。
      • 不在信号集内返回0。
    • 其余:
      • 成功返回0.
      • 失败返回-1,设置errno.

    sigprocmask函数

    来屏蔽信号、解除屏蔽也使用该函数。其本质,读取或修改进程的信号屏蔽字(PCB中)。

    注意:

    • 屏蔽信号:只是将信号处理延后执行(延至解除屏蔽)+
    • 忽略信号:表示将信号丢弃。

    函数原型:

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

    参数解释

    • how: 设置方式。
      • SIG_BLOCK: 设置为阻塞。
      • SIG_UNBLOCK: 设置为非阻塞。
      • SIG_SETMASK:设置一个新的屏蔽集合为set。
    • set: 新设置的信号集。
    • oldset: 返回上一次信号集。保护现场。

    返回值

    • 成功调用返回0.
    • 失败调用返回-1,设置errno.

    sigpending函数

    函数原型:

    #include <signal.h>
    int sigpending(sigset_t *set);
    
    • set是传出参数。
    • 此函数将传入的set填充为当前的信号集,可以看到未决信号。通过sigismember函数调用可以知道指定的信号是否未决。

    sigaction函数

    注册需要捕获的信号的函数。

    我们以后最常用的就是sigaction函数,和signal一样它也是一个捕获信号执行自定义行为的函数,同样用来防止进程的意外死亡。但是它提供更加丰富的机制。

    函数原型

    #include <signal.h>
    int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
    

    其中,struct sigaction结构体为:

    struct sigaction {
        void     (*sa_handler)(int);
        void     (*sa_sigaction)(int, siginfo_t *, void *);
        sigset_t   sa_mask;
        int        sa_flags;
        void     (*sa_restorer)(void);
    };
    

    struct sigaction结构体成员:

    • (*sa_restorer)(void): 不需要设置。
    • sa_flags:
      • 一般设置为0,捕获信号后会执行第一个成员函数sa_handler.
      • 如果指定为SA_SIGINFO,则捕获后执行第二个成员函数sa_sigaction。
    • sa_mask: 在处理函数执行期间,原本被屏蔽的信号集不再是PCB中所屏蔽的。此时需要指定在处理函数期间需要屏蔽的信号集 (如果处理函数需要执行很久,那么设置这个信号集很有必要)。是临时性的设置,出了处理函数之后将无效。

    参数解释

    • signum: 注册的信号。
    • act: 上述已经解释,根据实际情况设置好。
    • oldact: 传出参数,返回上一次设置的act。用以保护现场。

    返回值

    • 成功调用返回0.
    • 失败调用返回-1,且设置好errno.

    Note

    信号捕捉的特性

    • 进程正常运行时,默认PCB中有一个信号屏蔽字,假定为☆,它决定了进程自动屏蔽哪些信号。当注册了某个信号捕捉函数,捕捉到该信号以后,要调用该函数。而该函数有可能执行很长时间,在这期间所屏蔽的信号不由☆来指定。而是用sa_mask来指定。调用完信号处理函数,再恢复为☆。
    • XXX信号捕捉函数执行期间,XXX信号自动被屏蔽。
    • 阻塞的常规信号不支持排队,产生多次只记录一次。(后32个实时信号支持排队)。

    实例

    最后来个实例吧。

    void catchSignal(int signal)
    {   
        printf("catch signal:%d
    ", signal);
        //模拟捕捉执行时间长的时候,新来的同样信号和屏蔽信号会怎样?
        //结论是会被阻塞,在未决信号集中置1,此函数执行完会去捕捉。
        //但是多个信号过来,只会捕捉一次。
        sleep(2);   
        printf("cat end.
    ");
    }
    
    int main()
    {
        sigset_t sigset;
        sigemptyset(&sigset);
        sigaddset(&sigset, SIGQUIT);
        
        //设置阻塞,执行处理函数期间能够正确捕捉到一个SIGQUIT等待处理
        sigprocmask(SIG_BLOCK, &sigset, NULL);
        
        // 初始化sigaction结构体
        struct sigaction sigac;
        sigac.sa_flags = 0;
        sigac.sa_handler = catchSignal;
        
        //信号捕捉期间阻塞SIGQUIT
        sigac.sa_mask = sigset;
        //注册捕捉函数
        sigaction(SIGINT, &sigac, NULL);
        while(1)
        {
          printf("wait for signal...
    ");
          sleep(1);
        }
        return 0;
    }
    

    总结一下通常步骤:

    1. 定义一个信号集,把需要屏蔽的信号加进去。
    2. 设置好sigaction结构体,把处理函数和屏蔽函数加进去。
    3. 注册捕获信号的函数。
    4. 开始执行。

    以上。

  • 相关阅读:
    自定义Toast
    自定义控件三部曲之动画篇(四)——ValueAnimator基本使用
    关于ShapeDrawable应用的一些介绍(下)
    关于ShapeDrawable应用的一些介绍(中)之Gradient
    关于ShapeDrawable应用的一些介绍(上)
    android 经典博客
    PopUpWindow使用详解(二)——进阶及答疑
    详解Dialog(二)——有关列表的构建
    安装eclipse的maven插件
    fragment.setMenuVisibility setUserVisibleHint
  • 原文地址:https://www.cnblogs.com/love-jelly-pig/p/10069566.html
Copyright © 2020-2023  润新知