sigprocmask、sigpending

1.介绍

sigprocmask是UNIX或Linux系统编程中一个重要的系统调用,它可以用来改变进程的信号掩码。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
  • how:决定如何修改当前信号掩码。有三种可能的值:

    • SIG_BLOCK:将set中的信号添加到当前的信号掩码中,这样就会阻塞set中的信号。

    • SIG_UNBLOCK:将set中的信号从当前的信号掩码中删除,这样就不会阻塞set中的信号。

    • SIG_SETMASK:将当前的信号掩码设置为set指向的值。

  • set:指向一个信号集,这个信号集用来改变当前的信号掩码。

  • oldset:如果不是NULL,则在修改信号掩码之前,旧的信号掩码将被保存在这里。

这个函数的返回值是0,如果成功,-1如果失败。如果失败,errno将被设置为相应的错误。

2.例子

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
​
int main() {
    sigset_t newmask, oldmask, pending;
​
    // 初始化一个包含 SIGINT 的新信号集
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGINT);
​
    // 将当前信号掩码设置为新信号集,保存旧的信号掩码
    if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
        perror("sigprocmask");
        return 1;
    }
​
    // 在一段时间内阻塞 SIGINT
    printf("SIGINT is now blocked for 5 seconds.\n");
    sleep(5);
​
    // 检查是否有挂起的 SIGINT
    if (sigpending(&pending) < 0) {
        perror("sigpending");
        return 1;
    }
    if (sigismember(&pending, SIGINT)) {
        printf("SIGINT is pending.\n");
    }
​
    // 将信号掩码恢复到原始状态
    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
        perror("sigprocmask");
        return 1;
    }
    printf("SIGINT is no longer blocked.\n");
​
    return 0;
}

在这个例子中,我们首先创建了一个新的信号集 newmask ,并将 SIGINT 添加到这个集合中。然后我们调用 sigprocmask ,将当前的信号掩码设置为 newmask ,并将旧的信号掩码保存在 oldmask 中。接着我们让进程休眠5秒,期间 SIGINT 信号是阻塞的。在休眠结束后,我们检查是否有挂起的 SIGINT 信号,然后再次调用 sigprocmask ,将信号掩码恢复到原始状态。

注意,如果在信号被阻塞的期间,这个信号发生了,那么这个信号就是挂起的。当信号再次被解阻塞时,这个信号就会被立即传递给进程。在该函数返回之前,至少要将其中之一递送给该进程。

3.信号集sigset_t的含义

sigset_t数据结构表示的是一个信号集合,每一位对应一个信号。当某位被设置为1时,表示对应的信号被加入到这个集合中;当某位被设置为0时,表示对应的信号被从这个集合中删除。但这个信号集合是怎么被使用的,取决于你使用它的上下文。

sigprocmask的上下文中,sigset_t中的1代表阻塞对应的信号,0代表不阻塞对应的信号。所以,对于sigprocmask函数,sigset_t的解释应该是这样的:

  • 如果你使用 SIG_BLOCK,那么sigprocmask将把set参数指向的信号集中的所有信号添加到进程的信号掩码中。这就意味着,所有在set中设置为1的信号将被阻塞。

  • 如果你使用 SIG_UNBLOCK,那么sigprocmask将把set参数指向的信号集中的所有信号从进程的信号掩码中删除。这就意味着,所有在set中设置为1的信号将被解阻塞。

  • 如果你使用 SIG_SETMASK,那么sigprocmask将把进程的信号掩码设置为set参数指向的信号集。这就意味着,所有在set中设置为1的信号将被阻塞,而所有在set中设置为0的信号将被解阻塞。

    信号集仅仅是个集合,1不一定代表屏蔽也不一定代表不屏蔽。

七、sigpending

1.介绍

sigpending() 用于获取当前进程或线程的未决信号集。

#include <signal.h>
​
int sigpending(sigset_t *set);

该函数接受一个 sigset_t 类型的指针作为参数,这个指针指向一个信号集。当函数返回时,这个信号集中的位被设置为当前进程的未决信号。

sigpending() 返回 0 表示成功,-1 表示失败。如果失败,错误代码会被设置在 errno 中。

2.例子

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
​
void handler(int sig) {
  printf("Received signal %d\n", sig);
}
​
int main() {
  signal(SIGUSR1, handler);
  
  sigset_t sig;
  sigemptyset(&sig);
  sigaddset(&sig,SIGUSR1);
  sigprocmask(SIG_BLOCK, &sig, NULL);
  
  printf("Sending signal %d\n", SIGUSR1);
  raise(SIGUSR1);
  
  if (sigpending(&sig) == 0) {
    if (sigismember(&sig, SIGUSR1)) {
      printf("Signal %d is pending\n", SIGUSR1);
    } else {
      printf("Signal %d is not pending\n", SIGUSR1);
    }
  } else {
    printf("sigpending failed\n");
  }
  
  return 0;
}
​
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值