Unix环境高级编程(阅读笔记)----信号集、信号屏蔽函数sigprocmask
2016-05-12 15:48
711 查看
信号屏蔽字是指一个进程中当前阻塞而不能够递送给该进程的信号集。
信号集则是一个能表示多个信号的集合的一种数据类型,为sigset_t。
与信号集设置相关的函数有如下几个:
// 下列四个函数成功返回0,出错返回-1
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
/*
* 下面函数若真返回1,若假返回0,出错返回-1
*/
int sigismember(const sigset_t *set, int signo);
要注意的是,所有应用程序在使用信号集前,要对信号集调用sigemptyset或sigfillset一次。这是因为C编译器把未赋初值的外部和静态变量都初始化为0,而这是否与给定的信号集实现对应却并不清楚。
设置信号屏蔽字则要调用下面函数:
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
how取值有下列三个:
SIG_BLOCK :set中包含的是希望阻塞的附加信号
SIG_UNBLOCK:set中包含的是希望解除阻塞的信号
SIG_SETMASK:set中包含的是现有屏蔽字的代替值
若oset是非空指针,则返回进程的当前信号屏蔽字。
若set为空,则进程信号屏蔽字不变,how值无意义。
另外,注意一点,不可以阻塞SIGKILL和SIGSTOP信号。
要想处理关于信号屏蔽字的问题,还需要一个函数,就是sigpending,原型如下:
int sigpending(sigset_t *set);
此函数通过set返回当前正在阻塞的信号的信号集。
CTRL+C--->SIGINT
CTRL+Z---->SIGTSTP
CRL+/----->SIGQUIT
下面通过一个实例理解一下这几个函数的用法:
1. #include <stdio.h>
2. #include <stdlib.h>
3. #include <unistd.h>
4. static void sig_quit(int);
5. static void err_quit(const char *str)
6. {
7. perror(str);
8. exit(-1);
9. }
10. int main(void)
11.
{
12. sigset_t newmask, oldmask, pendmask;
13. if (signal(SIGQUIT, sig_quit) == SIG_ERR)
14.
err_quit("can't catch SIGQUIT");
15.
sigemptyset(&newmask);
16. sigaddset(&newmask, SIGQUIT);
17.
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
18. err_quit("SIG_BLOCK error");
19. sleep(5);
20. if (sigpending(&pendmask) < 0)
21.
err_quit("sigpending error");
22. if (sigismember(&pendmask, SIGQUIT))
23.
printf("\nSIGQUIT pending\n");
24.
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
25. err_quit("SIG_SETMASK error");
26.
printf("SIGQUIT unblocked\n");
27.
sleep(5);
28. exit(0);
29.
}
30.
static void sig_quit(int signo)
31. {
32.
printf("caught SIGQUIT\n");
33. if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
34.
err_quit("can't reset SIGQUIT");
35. }
在ubuntu12.04下运行结果如下
[unix]$ ./a.out
^\^\^\^\^\^\^\^\^\^\
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
^\退出 (核心已转储)
信号集则是一个能表示多个信号的集合的一种数据类型,为sigset_t。
与信号集设置相关的函数有如下几个:
// 下列四个函数成功返回0,出错返回-1
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
/*
* 下面函数若真返回1,若假返回0,出错返回-1
*/
int sigismember(const sigset_t *set, int signo);
要注意的是,所有应用程序在使用信号集前,要对信号集调用sigemptyset或sigfillset一次。这是因为C编译器把未赋初值的外部和静态变量都初始化为0,而这是否与给定的信号集实现对应却并不清楚。
设置信号屏蔽字则要调用下面函数:
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
how取值有下列三个:
SIG_BLOCK :set中包含的是希望阻塞的附加信号
SIG_UNBLOCK:set中包含的是希望解除阻塞的信号
SIG_SETMASK:set中包含的是现有屏蔽字的代替值
若oset是非空指针,则返回进程的当前信号屏蔽字。
若set为空,则进程信号屏蔽字不变,how值无意义。
另外,注意一点,不可以阻塞SIGKILL和SIGSTOP信号。
要想处理关于信号屏蔽字的问题,还需要一个函数,就是sigpending,原型如下:
int sigpending(sigset_t *set);
此函数通过set返回当前正在阻塞的信号的信号集。
CTRL+C--->SIGINT
CTRL+Z---->SIGTSTP
CRL+/----->SIGQUIT
下面通过一个实例理解一下这几个函数的用法:
1. #include <stdio.h>
2. #include <stdlib.h>
3. #include <unistd.h>
4. static void sig_quit(int);
5. static void err_quit(const char *str)
6. {
7. perror(str);
8. exit(-1);
9. }
10. int main(void)
11.
{
12. sigset_t newmask, oldmask, pendmask;
13. if (signal(SIGQUIT, sig_quit) == SIG_ERR)
14.
err_quit("can't catch SIGQUIT");
15.
sigemptyset(&newmask);
16. sigaddset(&newmask, SIGQUIT);
17.
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
18. err_quit("SIG_BLOCK error");
19. sleep(5);
20. if (sigpending(&pendmask) < 0)
21.
err_quit("sigpending error");
22. if (sigismember(&pendmask, SIGQUIT))
23.
printf("\nSIGQUIT pending\n");
24.
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
25. err_quit("SIG_SETMASK error");
26.
printf("SIGQUIT unblocked\n");
27.
sleep(5);
28. exit(0);
29.
}
30.
static void sig_quit(int signo)
31. {
32.
printf("caught SIGQUIT\n");
33. if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
34.
err_quit("can't reset SIGQUIT");
35. }
在ubuntu12.04下运行结果如下
[unix]$ ./a.out
^\^\^\^\^\^\^\^\^\^\
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
^\退出 (核心已转储)
相关文章推荐
- Yii 2.0邮箱类的简单应用
- C++输入cout与输出cin
- [转发]SPRING MVC3.2案例讲解--SPRING MVC3的@ResponseBody和ResponseEntity
- java发送http请求并获取状态码的简单实例
- C#最基本的Socket编程
- 代码阅读——十个C开源项目
- Spring Data Cassandra 说明文档
- ubuntu 安装jdk及配置环境变量
- SpringMVC文件上传的配置实例详解
- Java注解教程:自定义注解示例,利用反射进行解析
- Java 中的super和this区分
- 【java开发系列】—— 自定义注解
- Yii 2.0邮箱类简单应用
- IntelliJ IDEA导入JDK源码
- Visual Studio Code 使用 ESLint 增强代码风格检查
- thinkphp 3.2 unionall
- 【c++】第十二周上机实践作业 项目 4
- java正则表达式基本符号
- 玩转Django的POST请求 CSRF
- Java 多线程 编程 教程