sigset 与 signal的区别?

阅读《深入理解UNIX系统内核》的时候,了解到了关于信号的使用。回想起之前自己用过 signal()来处理信号,但是当时实践的时候有个错误的理解:信号处理只捕获一次信号,后面的信号都没捕获到,因为没有调用我的信号处理函数。现在看来,理解错误,不是因为没捕获到,而是捕获到了,但是使用的是默认的信号处理函数处理了。

SVR2的unix版本中的信号机制是不可靠的,存在很多缺陷,最重要的问题是信号的可靠传送。信号处理函数不是持久有效的,而且在执行时不会屏蔽相应信号(即在执行信号处理函数的时候,有可能收到新的信号,不屏蔽的做法是:不会阻塞新信号,会直接传递给本进程,屏蔽的做法是:如果新信号是设为阻塞的话,那么内核就会记住它,但不会立刻传递给进程,当进程取消对新信号的阻塞后,信号将会由内核传递给进程,并在进程中得到处理,这允许程序员保护代码的临界区,防止来自一些信号的破坏)。在这个信号机制下,有一个signal()函数。书中有这么一段话:

“假设用户为一个特殊的信号设置了一个信号处理函数,当该信号发生时,内核会在调用该处理函数之前将信号的处理动作设置为默认动作。如果用户希望捕捉信号的再次发送,则每次都必须重新设置这个处理函数。”

也就是说,使用signal()的正确方法是这样:

void sigint_handler(sig)

int sig;

{

       signal(SIGINT,sigint_handler);

        ……

}

main()

{

        signal(SIGINT,sigint_handler);

}

而 sigset 系统调用制定一个持久的信号处理函数,在信号发生时,不会被重置为默认处理动作。旧的 signal 调用被保留下来以便向后兼容,由 signal 指定的处理函数不是持久性的。

但是我在自己的机器上面尝试用 signal 捕获 SIGINT 信号,即便不在 sigint_handler()中再次设置信号的处理函数,下次信号到达的时候,也会调用我的信号处理函数,而不需要在信号处理函数中再次设置信号处理函数。也许是现在的版本是 SVR4或者BSD, signal 优化成了持久性吧。不过记下此文,提醒自己,以后尽量使用sigset,少用 signal。

转载于:https://my.oschina.net/u/2447371/blog/1541117

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
sigset_t 是一个用于存储信号集合的数据类型,它是一个位图,每个位代表一个信号。在使用 sigset_t 之前,需要先使用 sigemptyset 函数将其初始化为空集。 sigset_t 可以用于设置线程或进程的信号掩码,即哪些信号会被阻塞或接收。可以使用 sigaddsetsigdelset 函数向信号集合中添加或删除信号。sigismember 函数用于判断信号是否在信号集合中。 下面是一个简单的例子,演示了 sigset_t 的基本用法: ```c #include <stdio.h> #include <stdlib.h> #include <signal.h> int main() { sigset_t set; // 初始化为空集 sigemptyset(&set); // 添加 SIGINT 和 SIGTERM 信号 sigaddset(&set, SIGINT); sigaddset(&set, SIGTERM); // 判断 SIGINT 和 SIGKILL 是否在信号集合中 if (sigismember(&set, SIGINT)) { printf("SIGINT is in the signal set\n"); } if (sigismember(&set, SIGKILL)) { printf("SIGKILL is in the signal set\n"); } // 删除 SIGTERM 信号 sigdelset(&set, SIGTERM); // 判断 SIGTERM 是否在信号集合中 if (sigismember(&set, SIGTERM)) { printf("SIGTERM is in the signal set\n"); } else { printf("SIGTERM is not in the signal set\n"); } return 0; } ``` 在上面的例子中,我们首先使用 sigemptyset 函数将 sigset_t 初始化为空集。然后使用 sigaddset 函数向信号集合中添加 SIGINT 和 SIGTERM 信号,使用 sigismember 函数判断 SIGINT 和 SIGKILL 是否在信号集合中。接着使用 sigdelset 函数将 SIGTERM 信号从信号集合中删除,最后再次使用 sigismember 函数判断 SIGTERM 是否在信号集合中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值