zoukankan      html  css  js  c++  java
  • APUE学习笔记——10.11~10.13 信号集、信号屏蔽字、未决信号

    如有转载,请注明出处:Windeal专栏

    首先简述下几个概念的关系:

    我们通过信号集建立信号屏蔽字,使得信号发生阻塞,被阻塞的信号即未决信号。

    信号集:

    信号集:其实就是一系列的信号。用sigset_t set表示。
    数据类型:sigset_t 类似于整型(位数可能超过整型,因而不能用整型表示)。
    我们一般在sigprocmask()等函数中使用信号集,用于创建一系列进程要阻塞的信号,告诉内核不允许这些信号发生。
    几个关于信号集的函数:
    #include <signal.h>
    int sigemptyset(sigset_t *set);        //清空信号集
    int sigfillset(sigset_t *set);        //填满信号集
    int sigaddset(sigset_t *set,int signo);    //添加一个信号
    int sigdelset(sigset_t *set,int signo);    //删除信号集中的一个信号
                                   All four return: 0 if OK,−1 on error
    int sigismember(const sigset_t *set,int signo);
                                   Returns: 1 if true, 0 if false,−1 on error



    信号集函数的实现

    《APUE》中假设系统只有31种信号,且整型是32bit的,也就是说我们整型的每一位可以代表一个信号(注意其它系统的实现方法可能不是这样的,这里只是做一个思路)
    实现:
    sigemptyset 和 sigfillset用宏实现
    #define sigemptyset(ptr) (*(ptr) = 0)
    #define sigfillset(ptr) (*(ptr) = ˜(sigset_t)0, 0)

    sigaddset、sigdelset和sigismember用函数实现:
    #include  <signal.h>
    #include  <errno.h>
    /*
    *<signal.h> usually defines NSIG to include signal number 0.
    */
    #define SIGBAD(signo) ((signo) <= 0 || (signo) >= NSIG)
    int
    sigaddset(sigset_t *set, int signo)
    {
        if (SIGBAD(signo)) {
            errno = EINVAL;
            return(-1);
        }
        *set |= 1 << (signo - 1); /* turn bit on */
        return(0);
    }
    int
    sigdelset(sigset_t *set, int signo)
    {
        if (SIGBAD(signo)) {
            errno = EINVAL;
            return(-1);
        }
        *set &= ˜(1 << (signo - 1)); /* turn bit off */
        return(0);
    }
    int
    sigismember(const sigset_t *set, int signo)
    {
        if (SIGBAD(signo)) {
            errno = EINVAL;
            return(-1);
        }
        return((*set & (1 << (signo - 1))) != 0);
    }



    信号屏蔽字与sigprocmask

    信号屏蔽字用信号集来表示,该信号集中的信号在进程中被屏蔽,我们经常用sigprocmask函数实现:
    #include <signal.h>
    int sigprocmask(int how,const sigset_t *restrict set,sigset_t *restrict oset);
                                                        Returns: 0 if OK,−1 on error

    参数:
    oset:如果非空,表示当前信号屏蔽字,就是在执行这个函数之前的信号屏蔽字,
    set:如果非空,表示接下来要进行修改的信号屏蔽字,how表示修改方式:set参数的角色根据how而定。
    how:取值如下:

    SIG_BLOCK:   期望的信号屏蔽字是set和原信号屏蔽字的并集
    SIG_UNBLOCK:期望的信号屏蔽字是set和原来信号屏蔽字的补集的交集,也就是原来的信号屏蔽字解除掉属于set的部分
    SIG_SETMASK:直接用set替换掉当前信号屏蔽字

    未决信号与sigpending

    信号阻塞而不能递送时,该信号对于调用进程来说是未决的,
    我们用sigpending获取这些未决信号:
    #include <signal.h>
    int sigpending(sigset_t *set);
                                   Returns: 0 if OK,−1 on error

    set用于保存未决信号。
    使用sigpending只能返回未决的信号有哪些,而无从得知某个未决信号发生了几次(不支持排队)。

    附上一个《APUE》上跟许多信号功能相关的例子:
    $./a.out
    ˆ generate signal once (before5seconds areup)
    SIGQUIT pending after return fromsleep
    caught SIGQUIT in signal handler
    SIGQUIT unblocked after return fromsigprocmask
    ˆQuit(coredump) generate signal again
    $./a.out
    ˆˆˆˆˆˆˆˆˆˆ generate signal 10 times (before5seconds areup)
    SIGQUIT pending
    caught SIGQUIT signal is generated only once
    SIGQUIT unblocked
    ˆQuit(coredump) generate signal again



    sigsuspend()

        用于解除信号屏蔽字的函数(原子操作)。
    #include <signal.h>
    int sigsuspend(const sigset_t *sigmask);
                  Returns:−1witherrnoset toEINTR
















    sigsuspend()

        用于解除信号屏蔽字的函数(原子操作)。
    1. #include <signal.h>
    2. int sigsuspend(const sigset_t *sigmask);
    3. Returns:−1witherrnoset toEINTR

  • 相关阅读:
    java基础之switch
    String的getBytes()方法
    Android adb命令
    shell中grep命令详解
    su root 和su
    adb shell 命令详解
    adb shell am 的用法
    adb logcat 基本用法
    Android、iOS和Windows Phone中的推送技术
    Android客户端消息推送原理简介
  • 原文地址:https://www.cnblogs.com/Windeal/p/4284648.html
Copyright © 2011-2022 走看看