Chinaunix首页 | 论坛 | 博客
  • 博客访问: 393947
  • 博文数量: 85
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1707
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-27 11:18
个人简介

学无止境……

文章分类

全部博文(85)

分类: LINUX

2014-07-04 16:38:12

在之前的博文中介绍了linux下的多进程间通讯机制:“信号”。其中有个很重要的概念:信号集。在这着重介绍下它和与它相关的函数。

概念:

信号集是一个能表示多个信号的数据类型,sigset_t set ;set即一个信号集。在信号机制中的一个重要结构(struct sigaction)中就使用了信号集的概念,此结构中的sa_mask成员就是信号集变量。

相关函数:
信号集,主要与信号阻塞相关函数配合使用,创建信号集有如下函数:
  1. #include<signal.h>

  2. int sigemptyset(sigset_t *set); // 初始化信号集,并置空
  3. int sigfillset(sigset_t *set); // 将所有信号加入set集合
  4. int sigaddset(sigset_t *set, int signo); // 添加信号至信号集中
  5. int sigdelset(sigset_t *set, int signo); // 把信号从信号集中删除

  6. int sigismember(const sigset_s *set, int signum); // 用于判断信号集中是否存在该信号,存在函数返回 1;否则返回 0;出错返回 -1.

信号阻塞及相关函数:
信号的阻塞就是让系统暂时保留信号待以后发送。由于另外有办法让系统忽略信号,所以一般情况下信号的阻塞只是暂时的,延迟信号的到达。信号会在解除阻塞后继续传递,只是为了防止信号打断敏感的操作。相关的函数如下:
  1. #include<signal.h>

  2. int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
  3. int sigpending(sigset_t *set);
  4. int sigsuspend(const sigset_t *sigmask);
sigprocmsk()
把指定信号加入到阻塞队列中

    how : 决定如何操作信号,常用值如下
                SIG_BLOCK:    阻塞set中包含的信号,意思是说把set中的信号加到当前的信号掩码中去不可以阻塞SIGKILLSIGSTOP信号
                SIG_UNBLOCK:  解除set中信号的阻塞,从当前信号掩码中去除set中的信号
                SIG_SETMASK:  设置信号掩码,按照set中的信号重新设置信号掩码
    oldset:非空时当前进程信号阻塞结合会保存在oldset中
    set:被操作的信号集

sigpending()
获得当前正在阻塞的信号
        set: 存放正在被阻塞的信号集

sigsuspend()
临时用mask替换进程的信号掩码,并暂停进程执行,直到收到信号为止。也就是说,sigsuspend后,进程就挂在那里,等待着开放的信号的唤醒。系统在接收到信号后,调用处理函数,然后把现在的信号集还原为原来的。
该系统调用始终返回 -1,并设置 errno 为 EINTR.
注:sigsuspend() 和 pause()函数都用于休眠程序,等待被信号唤醒。但是它们在使用中有一定区别。将在其他的博文中详细解释。http://blog.chinaunix.net/uid-29145190-id-4341878.html




参考代码:

点击(此处)折叠或打开

  1. /***********************************************/
  2. /*          简介:信号集相关函数示例。            */
  3. /***********************************************/
  4. #include <signal.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. static void sig_quit(int signo)
  8. {
  9.     printf("caught SIGQUIT\n");
  10.     if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
  11.         perror("can't reset SIGQUIT");
  12. }
  13. static void sig_int(int signo)
  14. {
  15.     printf("caught SIGINT\n");
  16.     if (signal(SIGINT, SIG_DFL) == SIG_ERR)
  17.         perror("can't reset SIGINT");
  18. }

  19. int main(void)
  20. {
  21.     sigset_t    newmask, oldmask, pendmask;

  22.     if (signal(SIGQUIT, sig_quit) == SIG_ERR)
  23.         perror("can't catch SIGQUIT");
  24.     if (signal(SIGINT, sig_int) == SIG_ERR)
  25.         perror("can't catch SIGINT");

  26.     sigemptyset(&newmask);
  27.     /* 添加信号SIG_BLOCK和SIGINT至信号集*/
  28.     sigaddset(&newmask, SIGQUIT);
  29.     sigaddset(&newmask, SIGINT);
  30.     /* 设置为屏蔽这两个信号并保存当前的信号屏蔽字 */
  31.     if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
  32.         perror("SIG_BLOCK error");

  33.     sleep(5);/*进程休眠期间将阻塞的信号放置信号阻塞队列中*/

  34.     if (sigpending(&pendmask) < 0)
  35.         perror("sigpending error");
  36.     /*处理信号阻塞队列*/
  37.     if (sigismember(&pendmask, SIGQUIT))
  38.         printf("SIGQUIT pending\n");
  39.     if (sigismember(&pendmask, SIGINT))
  40.         printf("SIGINT pending\n");

  41.     /* 恢复最初的信号屏蔽字 */
  42.     if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
  43.         perror("SIG_SETMASK error");
  44.     fprintf(stderr,"SIGNAL unblocked\n");

  45.     sleep(5);        
  46.     exit(0);
  47. }

 
阅读(1571) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~