信号阻塞

更新时间:
2024-01-09
下载文档

信号阻塞

本节介绍信息阻塞的使用方法。

#include <signal.h>
int   sigsuspend(const sigset_t  *sigsetMask);
int   pause(void);

函数 sigsuspend 原型分析:

  • 此函数返回 -1。
  • 参数 sigsetMask 是指定的信号掩码。

函数 pause 原型分析:

  • 此函数返回 -1。

sigsuspend 函数将进程的当前信号屏蔽字设置为由 sigsetMask 指定的值,并且使得当前进程挂起,当 sigsetMask 中指定的某个信号到来后,因为屏蔽而不被处理,同时也不会影响进程的挂起状态,而 sigsetMask 之外的信号发生时,信号将执行并且从信号处理函数返回后,解除进程挂起状态并且 sigsuspend 函数将进程的信号屏蔽字设置为之前的值,返回值是 -1 并设置 errno 为 EINTR。

pause 函数将使调用进程挂起直到捕捉到任何一个信号,只有执行了一个信号处理函数并从其返回,pause 函数才返回,返回值是 -1 并设置 errno 为 EINTR。

修改信号屏蔽字可以屏蔽或解除屏蔽所选择的信号,使用这种技术可以保护不希望由信号中断的代码临界区,下面是一种保护临界区代码的方法。

……
sigprocmask(SIG_BLOCK, &newmask, &oldmask);
……                                               /*  临界区代码                       */
sigprocmask(SIG_SETMASK, &oldmask, NULL);
pause();
……

上面程序片段,使用 sigprocmask 函数屏蔽选择的信号,当临界区代码执行完毕后再解除被屏蔽的信号,然后调用 pause 函数等待屏蔽的信号递送。这个过程看似对临界区进行了很好的保护,但这里有一个很严重的问题,如果在 sigprocmask 函数解除屏蔽时刻和 pause 函数之间发生了信号,则 pause 函数可能会永远阻塞,也就是说在这个时间段,信号将会丢失。sigsuspend 函数可看成是这个过程的一个原子操作,因此调用 sigsuspend 函数将不会出现这样一个时间段。

以下函数将同步等待未决信号,同时解除屏蔽状态。如果有多个信号,则以串行的方式从小到大返回。

#include <signal.h>
int   sigwait(const sigset_t  *sigset, int  *piSig);
int   sigwaitinfo(const sigset_t *sigset, struct  siginfo  *psiginfo);

函数 sigwait 原型分析:

  • 此函数成功返回 0,失败返回-1 并设置错误号。
  • 参数 sigset 是指定的信号集。
  • 输出参数 piSig 返回未决的信号。

函数 sigtimedwait 原型分析:

  • 此函数成功返回 0,失败返回-1 并设置错误号。
  • 参数 sigset 是指定的信号集。
  • 输出参数 psiginfo 返回未决的信号信息。
  • 参数 ptv 是等超时值。

sigwait 函数使调用进程或者线程挂起,直到 sigset 中包含的信号未决,并将未决的信号通过 piSig 返回,此信号将从屏蔽字中删除,注意,sigset 中的信号是被屏蔽的。

sigwaitinfo 函数使调用进程或者线程挂起,直到 sigset 中包含的信号未决,并将未决的信号通过 psiginfo 返回,与 sigwait 函数不同的是,sigwaitinfo 函数以 siginfo_t类型返回信号信息,意味着将返回更多的信号信息。

如果没有未决的信号,则 sigwait 函数和 sigwaitinfo 函数将永远阻塞,有些时候,这种情况是程序所不允许的,调用 sigtimedwait 函数可以设置一个等待时间,其他功能同 sigwaitinfo 函数一样。需要注意的是,如果 ptv 为 NULL,则永远等待,直到产生未决的信号。

以下函数为信号等待提供了超时机制,当指定的时间超时时函数返回并设置 errno 为 EAGAIN。特殊地,如果参数 ptv 为 NULL,则永远等待直到信号未决。

#include <signal.h>
int   sigtimedwait(const sigset_t             *sigset, 
                   struct siginfo             *psiginfo,
                   const struct timespec      *ptv);

函数 sigtimedwait 原型分析:

  • 此函数成功返回 0,失败返回-1 并设置错误号。
  • 参数 sigset 是指定的信号集。
  • 输出参数 psiginfo 返回未决的信号信息。
  • 参数 ptv 是等待时间信息。

下面程序展示了 sigwait 函数的使用方法。

#include <stdio.h>
#include <signal.h>
int main (int argc, char *argv[])
{
    sigset_t  newmask;
    int       sig;
    int       ret;

    sigemptyset(&newmask);
    sigaddset(&newmask, SIGALRM);
    sigprocmask(SIG_BLOCK, &newmask, NULL);
    alarm(1);
    ret = sigwait(&newmask, &sig);
    if (!ret) {
        if (sig == SIGALRM) {
            fprintf(stdout, "Signal SIGALRM.\n");
        }
    }
    return  (0);
}

在 SylixOS Shell 下运行这段程序,从程序结果可以看出 sigwait 函数通过 sig 将被屏蔽的 SIGALRM 信号返回。

#./Sigwait_Usage
Signal SIGALRM.
文档内容是否对您有所帮助?
有帮助
没帮助