信号集和信号屏蔽函数
来源:互联网 发布:img网络图片无法显示 编辑:程序博客网 时间:2024/04/26 05:32
信号集是一个或多个信号的集合,主要用在信号屏蔽函数中。数据类型为sigset_t。
信号屏蔽字是指一个进程中当前阻塞而不能送给该进程的信号集。
与信号集设置相关的函数有下面几个:
#include <signal.h>
int sigemptyset(sigset_t *set);
功能:set为信号集,将信号集清空,对应将所有信号屏蔽字置0;
int sigfillset(sigset_t *set);
功能:将所有信号加入到信号集中,对应将所有信号屏蔽字置1;
int sigaddset(sigset_t *set, int signo);
功能:将某个信号加入到信号集中,对应将信号屏蔽字某位置1;
int delset(sigset *set, int signo);
功能:将某个信号从信号集中删除,对应将信号屏蔽字某位置0;
上述函数返回:成功返回0,出错返回-1;
int sigismember(const sigset_t *set, int signo);
功能:测试信号集中是否包含某个信号,对应判断信号屏蔽字某位是否为1;
返回值:真返回1,假返回0,出错返回-1;
注意:所有进程在使用信号集前,要对信号集调用sigemptyset或sigfillset一次。因为C编译器把未赋初值的外部和静态变量都初始化为0,而这与是否给定的信号集实现对应却并不清楚。
设置信号屏蔽字要调用下面的信号屏蔽函数。
#include <signal.h>
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
功能:利用set去覆盖内核中信号屏蔽字,oset存放原有的信号屏蔽字;
返回:成功返回0,出错返回-1;
int sigpending(sigset_t *set);
功能:获取信号未决字的内容(通过set返回当前正在阻塞的信号的信号集);
返回值:成功返回0,出错返回-1;
参数how
- SIG_BLOCK:利用set中信号设置信号屏蔽字;
- SIG_UNBLOCK:利用set中信号不设置信号屏蔽字;
- SIG_SETMASK:利用set中信号去替换内核信号屏蔽字;
说明:1 进程可以暂时屏蔽信号,使得进程在执行过程中发生的相应信号暂时被阻塞,等待进程解除信号屏蔽后再由内核或驱动将该 信号递送给进程;
2 信号屏蔽可屏蔽程序执行过程中的中断;
3 若oset是非空指针,则返回进程的当前信号屏蔽字;
4 若set为空,则进程信号屏蔽字不变,how值无意义;
5 注意,不可以阻塞SIGKILL和SIGSTOP信号;
下面给出一个mask(信号屏蔽字)的实例。
#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <signal.h>void out_set(sigset_t set){int i = 1;for(; i < 31; ++i){// 判断信号屏蔽字的某些位是否置1if(sigismember(&set, i)){printf("%d\n", i);}}}void sig_handler(int signo){printf("begin process the %d\n", signo);// 获得正在处理信号时内核中的信号屏蔽字内容sigset_t oset;sigemptyset(&oset);if(sigprocmask(SIG_BLOCK, NULL, &oset) < 0)perror("sigprocemask error");out_set(oset);// 输出处理信号时的信号屏蔽字printf("finish process the %d\n", signo);}int main(void){if(signal(SIGUSR1, sig_handler) == SIG_ERR)perror("signal sigusr1 error");if(signal(SIGUSR2, sig_handler) == SIG_ERR)perror("signal sigusr2 error");if(signal(SIGINT, sig_handler) == SIG_ERR)perror("signal sigint error");// 定义一个信号集sigset_t oset;//放置内核信号屏蔽字的内容printf("before signal occured mask:\n");// 清空信号集osetsigemptyset(&oset);//在信号发生前,获得信号屏蔽字的内容if(sigprocmask(SIG_BLOCK, NULL, &oset) < 0)perror("sigprocmask error");out_set(oset);//输出产生信号前的信号屏蔽字printf("process %d wait signal...\n", getpid());pause();// 进程暂停等待信号printf("after signal occured mask:\n");sigemptyset(&oset);// 信号发生后(信号处理完毕后),获得信号屏蔽字的内容if(sigprocmask(SIG_BLOCK, NULL, &oset) < 0)perror("sigprocmask error");out_set(oset);// 输出信号产生并处理完毕后的信号屏蔽字的内容 return 0;}程序分别输出信号产生前,处理信号时和信号处理完毕三个阶段的信号屏蔽字。
由结果可以看出,在信号产生前后,信号屏蔽字全置为了0。
下面给出一个pending(信号未决字)的实例。
#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <signal.h>void out_set(sigset_t set){int i = 1;for(; i <= 31; ++i){if(sigismember(&set, i)){printf("%d,", i);}}printf("\n");}void sig_handler(int signo){printf("begin the signal handler\n");int i = 0;sigset_t set;//循环不断去获得同类信号for(; i < 20; ++i){sigemptyset(&set);if(sigpending(&set) < 0)perror("sigpending error");else{printf("pending signal:");out_set(set);sigemptyset(&set);}printf("i is %d\n", i);sleep(1);}printf("end the signal handler\n");}int main(void){if(signal(SIGTSTP, sig_handler) == SIG_ERR)perror("signal sigtstp error");printf("process %d wait signal...\n", getpid());pause(); // 进程暂停等待信号printf("process finished\n");return 0;}在for循环中,我们不断的去获得SIGTSTP信号,当同时有两个及以上的SIGTSTP信号产生时,相应的信号未决字才被置为1。同时,如果产生多个SIGTSTP信号(2个以上),则只被处理两次,其他的被屏蔽掉。
利用信号屏蔽技术可以防止函数执行过程中被信号中断,下面给出一个实例来说明。
#include <signal.h>#include <stdio.h>#include <stdlib.h>int g_v[10];//全局变量int *h_v;//堆中的数据void set(int val){int a_v[10];// 局部变量int i = 0;//注意到这里的i是局部变量for(; i < 10; ++i){a_v[i] = val;g_v[i] = val;h_v[i] = val;sleep(1);//给一个发送信号的时间}printf("g_v:");for(i = 0; i < 10; ++i){if(i != 0)printf(",%d", g_v[i]);elseprintf("%d", g_v[i]);}printf("\n");printf("h_v:");for(i = 0; i < 10; ++i){if(i != 0)printf(",%d", h_v[i]);elseprintf("%d", h_v[i]);}printf("\n");printf("a_v:");for(i = 0; i < 10; ++i){if(i != 0)printf(",%d", a_v[i]);elseprintf("%d", a_v[i]);}printf("\n");}void sig_handler(int signo){if(signo == SIGTSTP){printf("SIGTSTP occured\n");set(20);// 在信号处理函数中又调用setprintf("end SIGTSTP\n"); }}int main(void){if(signal(SIGTSTP, sig_handler) == SIG_ERR)perror("signal sigtstp error");h_v = (int*)calloc(10, sizeof(int));printf("begin running main\n");//屏蔽信号(1~31)sigset_t sigset;sigemptyset(&sigset);sigfillset(&sigset);// 要屏蔽所有的信号//这里我们不需要获得原内核中的信号屏蔽字,第三个参数设为NULL if(sigprocmask(SIG_SETMASK, &sigset, NULL) < 0)perror("sigprocmask error"); set(10);//解除信号屏蔽if(sigprocmask(SIG_UNBLOCK, &sigset, NULL) < 0)perror("sigprocmask error");printf("end running main\n");return 0;}这里我们对“函数的可重入性”中的函数进行了改进。在执行set函数之前,先通过sigfillset函数和sigprocmask函数屏蔽了1~31号信号,这样的话,在执行set过程中如果发生了信号,则不会影响第一次的结果输出。后面我们对信号解除了屏蔽,这样的话,在第一次执行set中产生的信号仍然被捕获,再次执行set函数。运行结果如下:
在第一次赋值过程中产生了一个SIGTSTP信号。
- 信号集和信号屏蔽函数
- 设置信号集和信号屏蔽字
- 信号屏蔽函数
- 信号集与屏蔽信号
- 信号中断处理函数中的信号屏蔽
- APUE学习笔记——信号、信号集和进程信号屏蔽字
- linux信号集与信号屏蔽字
- 屏蔽信号
- 信号屏蔽
- 信号集与屏蔽字
- Unix环境高级编程(阅读笔记)----信号集、信号屏蔽函数sigprocmask
- 信号屏蔽字以及pthread_join函数
- Linux 信号和信号集
- Linux 信号和信号集
- 信号和槽函数
- Linux信号掩码和信号处理函数
- Linux信号、信号处理和信号处理函数
- Linux信号、信号处理和信号处理函数
- 测试typecho的sitemap插件
- PyScript启动出错:python could not be properly initialize
- 在Swing中展现报表
- hash的简单使用<找数字>
- zmq_msg_more
- 信号集和信号屏蔽函数
- 移动端1px解决方案
- 一种在嵌入式环境下的2D游戏栅格地图绘制方法
- zmq_msg_move
- 【C#】 运算符
- Vmware10+CentOS 6.4 x86_64位安装JDK详细
- iOS 微信SDK分享
- zmq_msg_init
- Preference 三种监听事件说明