赞
踩
在进程PCB中存在两个信号集:信号掩码(signal mask)、未决信号集(signal pending)。
两个信号集都是位图,每一位对应一个信号:
#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
函数功能:设定自定义信号集:
参数说明:
返回值说明:
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
函数功能:自定义位图设定完成后,要与mask位图进行位操作,以改变mask位图中的数据。
通过自定义的信号集set,用来和PCB中的mask信号屏蔽字进行位与、位或、取反位与等操作,用来改变mask信号屏蔽字的位图状态。就可以实现阻塞、未阻塞等操作。
参数说明:
返回值说明:
特别说明:
系统中什么时候产生什么信号是有规律的,用户进程不应随便对mask进行修改。因此在用户进程中的功能实现之后,应尽量使用sigprocmask的传出参数oldset恢复mask。
#include <signal.h>
int sigpending(sigset_t *set);
函数功能:获取当前进程中未决信号集的信息。
参数说明:
返回值说明:
【案例 1】以2号信号为例,通过位操作函数sigprocmask和sigpending获取信号状态。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
void printset(sigset_t *paraPed){
int i;
for(i = 1; i < 32; i ++){
if(sigismember(paraPed, i) == 1){
putchar('1');
}else{
putchar('0');
}//of if
printf("\n");
}//of for i
}//of printset
int main(){
sigset_t tempSet, tempOldSet, tempPed;
sigemptyset(&tempSet); //初始化
sigaddset(&tempSet, SIGINT); //将2号信号SIGINT加入tempSet
sigprocmask(SIG_BLOCK, &tempSet, &tempOldSet); //位操作
while(1){
sigpending(&tempPed);
printset(&tempPed);
sleep(1);
}//of while
return 0;
}//of main
执行程序,终端会不断打印进程PCB中的未决信号集。初始情况下进程未决信号集中的每一位都应为0,因此打印的信息如下:
00000000000000000000000000000000
使用kill命令或组合按键Ctrl+C驱使内核发送信号SIGINT给当前进程。进程第一次接收到信号SIGINT后,sigprocmask被触发,此后终端打印的信息如下:
01000000000000000000000000000000
之后继续向进程发送SIGINT信号,终端打印信息不变,说明信号SIGINT被成功屏蔽。
【案例2】信号操作集测试
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <sys/mman.h>
#include <errno.h>
#include <signal.h>//信号头文件
//该函数用于未决信号集的打印,传入未决信号的sigpending函数的传出参数
void print_set(sigset_t *paraset){
int i = 0;
for(;i<32;i++){
if(sigismember(paraset,i)){//查看信号在不在创建的信号集中,在返回1,不在返回0
printf("1");//在打印1字符
}else{
printf("0");//不在打印0字符
}//of if
}//of for
printf("\n");//添加换行符号
}//of print_set
void sys_error(const char* paraString){
perror(paraString);
exit(1);
}
int main(int argc,char* argv[]){
sigset_t tempSet;//创建的信号集
sigset_t tempOldset;//用于传出参数,旧的mask
sigset_t tempPdset;//用于未决信号集的传出,只读的。
sigemptyset(&tempSet);//清空信号集
sigaddset(&tempSet, SIGINT);//添加各种信号
sigaddset(&tempSet, SIGQUIT);
sigaddset(&tempSet, SIGBUS);
sigaddset(&tempSet, SIGKILL);
//设置信号屏蔽字
int tempRet = sigprocmask(SIG_BLOCK,&tempSet,&tempOldset);//将自我创建的信号集进行阻塞。
if(tempRet == -1){
sys_error("sigprocmask error");
}//of if
int tempRet1 = 0; //用于判断sigpending函数是否执行成功
while(1){
tempRet1 = sigpending(&tempPdset);//传出未决信号集pdset
if(tempRet1 == -1){
sys_error("sigpending error");
}
print_set(&tempPdset);//打印未决信号集
sleep(1);
}
return 0;
}
haitu@ubuntu:/opt/linux_test/signal/signal2$ ./sigset
10000000000000000000000000000000
10000000000000000000000000000000
10000000000000000000000000000000
10000000000000000000000000000000
^C10100000000000000000000000000000 //输入ctrl + c
10100000000000000000000000000000
10100000000000000000000000000000
10100000000000000000000000000000
//想要关掉的话,可以使用另一个窗口,使用 ps ajx 来查看该进程的pid
//使用命令kill -9 pid号 进行关闭该进程。(SIGKILL信号是不能够屏蔽的,也不能够忽略捕捉)
信号操作集函数的使用原理:
#使用kill -l命令可以获取到信号的列表
haitu@ubuntu:/opt/linux_test/signal/signal2$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
#***注意:其中 9 号和 19 号信号比较特殊,只能执行默认动作,不能忽略捕捉,不能设置阻塞。***
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。