Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1743668
  • 博文数量: 438
  • 博客积分: 9799
  • 博客等级: 中将
  • 技术积分: 6092
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-25 17:25
文章分类

全部博文(438)

文章存档

2019年(1)

2013年(8)

2012年(429)

分类: 系统运维

2012-03-30 19:29:25

我们需要一个数据类型来表示多个信号--一个信号集。我们在函数比如sigprocmask(下节)里使用它来告诉内核不允许这个集里的任何信号发 生。正如我们之前提到的,不同信号的数量可以超过整型的位数,所以一般来说,我们不能用一个整型来以为个信号一位的方式表示。POISX.1定义了数据类 型sigset_t来包含一个信号集,下面的5个函数用来操作信号集。



  1. #include <signal.h>

  2. int sigemptyset(sigset_t *set);

  3. int sigfillset(sigset_t *set);

  4. int sigaddset(sigset_t *set, int signo);

  5. int sigdelset(sigset_t *set, int signo);

  6. 成功返回0,错误返回-1.

  7. int sigismember(const sigset_t *set, int signo);

  8. 真返回1,假返回0,错误返回-1.


函 数sigemptyset初始化set指向的信号集,以便信号被排除。函数sigfillset初始化信号集以便所有的信号被包含。所有的应用都必须为每 个信号集调用一次sigemptyset或sigfillset,在使用信号集之前,因为我们不假定C对外部和静态变量的0的初始化对应于一个给定系统上 的信号集的实现。


一旦我们初始化了一个信号集,我们可以加上或删除集里指定的信号。函数sigaddset向一个已存在的集合加入一个信号,而sigdelset从一个信号删除一个信号。在所有接受一个信号集为参数的函数里,我们总是传入信号集的地址作为参数。


实现

如 果实现比一个整型位数更少的信号,那么一个信号集可以用每个信号一位的方式实现。在本节后面,假定一个实现有31个信号和32位的整型。 sigemptyset函数对这个整型清零,而sigfillset函数打开这个整型里的所有位。这两个函数可以实现为 头文件里的宏:
#define sigemptyset(ptr) (*(ptr) = 0)
#define sigfillset(ptr) (*(ptr) = ~(sigset_t)0, 0)


注意sigfillset必须返回0,除了打开信号集里的所有位,所以我们使用C的逗号操作符,它返回逗号后的值作为表达式的值。


使用这个实现,sigaddset打开一个信号位而sigdelset关闭一个信号位。sigismember测试一个特定的位。因为没有信号被编号为0,我们把信号号减1来得到执行的位。下面的代码展示了这些函数的实现:



  1. #include <errno.h>

  2. /* <signal.h usually defines NSIG to include signal number 0 */
  3. #define NSIG 32
  4. #define SIGBAD(signo) ((signo) <= 0 || (signo) >= NSIG)

  5. typedef int sigset_t;

  6. int
  7. sigaddset(sigset_t *set, int signo)
  8. {
  9.     if (SIGBAD(signo)) { errno = EINVAL; return(-1); }

  10.     *set |= (1 << (signo - 1)); /* turn bit on */
  11.     return(0);
  12. }

  13. int
  14. sigdelset(sigset_t *set, int signo)
  15. {
  16.     if (SIGBAD(signo)) { errno = EINVAL; return(-1); }

  17.     *set &= (1 << (signo - 1)); /* turn bit off */
  18.     return(0);
  19. }

  20. int
  21. sigismember(const sigset_t *set, int signo)
  22. {
  23.     if (SIGBAD(signo)) { errno = EINVAL; return(-1); }

  24.     return((*set & (1 << (signo -1))) != 0);
  25. }


我们可能想把这三个函数作为头文件里的单行的宏,但是POSIX.1要求我们检查信号号参数来验证并在它无效时设置errno。在宏里这样做比在一个函数里更难。
阅读(784) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~