学无止境……
分类: LINUX
2014-07-04 16:38:12
信号集是一个能表示多个信号的数据类型,sigset_t set ;set即一个信号集。在信号机制中的一个重要结构(struct sigaction)中就使用了信号集的概念,此结构中的sa_mask成员就是信号集变量。
信号集,主要与信号阻塞相关函数配合使用,创建信号集有如下函数:
- #include<signal.h>
- int sigemptyset(sigset_t *set); // 初始化信号集,并置空
- int sigfillset(sigset_t *set); // 将所有信号加入set集合
- int sigaddset(sigset_t *set, int signo); // 添加信号至信号集中
- int sigdelset(sigset_t *set, int signo); // 把信号从信号集中删除
- int sigismember(const sigset_s *set, int signum); // 用于判断信号集中是否存在该信号,存在函数返回 1;否则返回 0;出错返回 -1.
信号的阻塞就是让系统暂时保留信号待以后发送。由于另外有办法让系统忽略信号,所以一般情况下信号的阻塞只是暂时的,延迟信号的到达。信号会在解除阻塞后继续传递,只是为了防止信号打断敏感的操作。相关的函数如下:
sigprocmsk()
- #include<signal.h>
- int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
- int sigpending(sigset_t *set);
- int sigsuspend(const sigset_t *sigmask);
把指定信号加入到阻塞队列中
how : 决定如何操作信号,常用值如下
SIG_BLOCK: 阻塞set中包含的信号,意思是说把set中的信号加到当前的信号掩码中去(不可以阻塞SIGKILL和SIGSTOP信号)
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
参考代码:
点击(此处)折叠或打开
- /***********************************************/
- /* 简介:信号集相关函数示例。 */
- /***********************************************/
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- static void sig_quit(int signo)
- {
- printf("caught SIGQUIT\n");
- if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
- perror("can't reset SIGQUIT");
- }
- static void sig_int(int signo)
- {
- printf("caught SIGINT\n");
- if (signal(SIGINT, SIG_DFL) == SIG_ERR)
- perror("can't reset SIGINT");
- }
- int main(void)
- {
- sigset_t newmask, oldmask, pendmask;
- if (signal(SIGQUIT, sig_quit) == SIG_ERR)
- perror("can't catch SIGQUIT");
- if (signal(SIGINT, sig_int) == SIG_ERR)
- perror("can't catch SIGINT");
- sigemptyset(&newmask);
- /* 添加信号SIG_BLOCK和SIGINT至信号集*/
- sigaddset(&newmask, SIGQUIT);
- sigaddset(&newmask, SIGINT);
- /* 设置为屏蔽这两个信号并保存当前的信号屏蔽字 */
- if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
- perror("SIG_BLOCK error");
- sleep(5);/*进程休眠期间将阻塞的信号放置信号阻塞队列中*/
- if (sigpending(&pendmask) < 0)
- perror("sigpending error");
- /*处理信号阻塞队列*/
- if (sigismember(&pendmask, SIGQUIT))
- printf("SIGQUIT pending\n");
- if (sigismember(&pendmask, SIGINT))
- printf("SIGINT pending\n");
- /* 恢复最初的信号屏蔽字 */
- if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
- perror("SIG_SETMASK error");
- fprintf(stderr,"SIGNAL unblocked\n");
- sleep(5);
- exit(0);
- }