免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 10314 | 回复: 8
打印 上一主题 下一主题

如何屏蔽一个进程的所有信号 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-24 23:22 |只看该作者 |倒序浏览
如题,我编写了一个进程,但想屏蔽调所有信号,然后自己增加要处理的信号,该怎么处理。
看了一下资料,sigemptyset这个函数好像并不能实现啊?

论坛徽章:
0
2 [报告]
发表于 2009-11-25 13:45 |只看该作者
int singal(int sig, __sighandler_t handler)

可以给sig传送SIG_IGN这个参数来屏蔽某个信号




好像么有一次性屏蔽所有信号的功能,但是可以屏蔽特定信号。

论坛徽章:
0
3 [报告]
发表于 2009-11-25 13:57 |只看该作者
sigprocmask

论坛徽章:
0
4 [报告]
发表于 2009-11-25 14:20 |只看该作者
sigfillset

论坛徽章:
0
5 [报告]
发表于 2009-11-26 17:09 |只看该作者
曾做过signal相关的一点儿开发,谈谈我的一些理解。

首先,需要理解几个signal相关的函数。
  sigaddset(sigset_t* sigSet, int sigNum ) :  将信号sigNum 添加到信号集 sigSet 中;
  sigdelset(sigset_t* sigSet, int sigNum) : 将信号 sigNum 从信号集 sigSet 中删除;
  sigemptyset(sigset_t* sigSet) : 清空信号集;
  sigfillset(sigset_t* sigSet) : 在信号集中打开所有的信号。

但是这个时候只是定义好了如此一个信号集,还有对信号的操作函数:
   pthread_sigmask(int opCode, sigset_t* sigSet, sigset_t* oldSigSet) : opCode 指定了如何对 sigSet 里的信号进行处理。opCode 有三个值: SIG_BLOCK (将sigSet中的信号加到当前线程的屏蔽集中),SIG_UNBLOCK (将sigSet 中的信号从当前线程屏蔽集中删除),SIG_SETMASK (将sigSet 设为当前线程的屏蔽集)。 若oldSigSet != NULL,则将之前的信号屏蔽集存入其中。
   另外还有个函数 sigprocmask() 也有类似功能。区别是:pthread_sigmask() 是线程库函数,用于多线程进程。sigprocmask() 是旧的实现,用于单线程的进程。

  sigwait(sigset_t* sigSet, int* sigNum) : 当前线程等待 sigSet 中的信号。没有捕获到信号时,线程挂起;当捕获到时,函数返回,并将信号值存入 sigNum。
  sigaction(int sigNum, sigaction* newAct, sigaction* oldAct) :  捕获信号 sigNum,并调用相应的处理函数(定义在 newAct 中)。
  
虽然sigwait() 和 sigaction() 都是用于捕获信号,但两者还是有较大区别:sigwait() 是阻塞的,线程会一直挂起直到捕获到信号,并且对信号的处理是定义在 sigwait()后的,只会在当前线程内执行;而sigaction()是非阻塞的,当信号被捕获时,会由进程内当前被调度到的线程来执行处理函数(好像是,not very sure...),被哪个线程处理是随机的。
所以,sigaction()适用于对实时性要求很高的时候。而在普通情况下建议使用sigwait(),因为其具有较好的可控性。
另外,还需要注意的是,SIG_KILL(大家应该都用过kill -9 吧) 和 SIG_STOP 是不能被用户屏蔽或捕获的。

好了,当理解了这几个函数后,可以自己试着来对信号进行处理了。对于lz的需求,简单举例如下:
  sigset_t blockSet, waitSet;
  int sigNum;
  
  sigfillset(&blockSet);     // open all signals in blockSet
  pthread_sigmask(SIG_BLOCK, blockSet, NULL);  //block all signals (except SIG_KILL & SIG_STOP also) in current thread
  
  sigemptyset(&waitSet);     // empty all signals in waitSet
  sigaddset(&waitSet, SIG_XXX);    // a signal wanted to be captured
  sigaddset(&waitSet, SIG_YYY);    // another signal wanted to be captured
  
  if ( sigwait(&waitSet, &sigNum) != 0 )    // wait for wanted signals
  {
    perror("Error - sigwait() is failure!\n");
    exit(1);
  }
  
  switch (sigNum)
  {
    case SIG_XXX:
      printf("SIG_XXX is captured!\n");
      break;
   
    case SIG_YYY:
      printf("SIG_YYY is captured!\n");
      break;
      
    default:
      printf("Error - cannot reach here!\n");
      exit(1);
  }
  
  return OK;

另外,用 sigaction() 也可以实现。

评分

参与人数 1信誉积分 +10 收起 理由
yjh777 + 10 赞一个! 谢谢分享

查看全部评分

论坛徽章:
0
6 [报告]
发表于 2016-01-02 13:37 |只看该作者
SIGKILL和SIGSTOP是不能屏蔽、阻塞和忽略的,不然的话,内核怎么做老大。回复 1# wbrucelee


   

论坛徽章:
0
7 [报告]
发表于 2016-01-02 13:38 |只看该作者
SIGKILL和SIGSTOP是不能屏蔽、阻塞和忽略的,不然的话,内核怎么做老大。回复 1# wbrucelee


   

论坛徽章:
0
8 [报告]
发表于 2016-01-04 15:06 |只看该作者
有些信号是不能屏蔽的,高级编程上面好像有讲到

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
9 [报告]
发表于 2016-01-09 10:56 |只看该作者
谢谢 5 楼分享,很详细啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP