目录
一、信号阻塞与信号未决
二、pause(2)的使用
三、信号传送过程处理
四、可重入函数
五、编写代码实现信号处理函数的继承
六、setitimer实现定时器
一、信号阻塞与信号未决
进程可以对某个信号设置阻塞或屏蔽,可是使用sigset_t(信号集)这个数据类型进行操作,对sigset_t操作的函数函数:
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);
int sigaction( int sig, const struct sigaction *act,struct sigaction *oact );
各个函数对应的功能如下:
sigemptyset(sigset_t *set)初始化由set指定的信号集,信号集里面的所有信号被清空;
sigfillset(sigset_t *set)调用该函数后,set指向的信号集中将包含linux支持的64种信号;
sigaddset(sigset_t *set, int signum)在set指向的信号集中加入signum信号;
sigdelset(sigset_t *set, int signum)在set指向的信号集中删除signum信号;
sigismember(const sigset_t *set, int signum)判定信号signum是否在set指向的信号集中。
int sigaction( int sig, const struct sigaction *act,struct sigaction *oact )检查、修改和指定信号相关联的信号响应。
sigset操作函数
#include<signal.h>
int sigemptyset(sigset_t *set);
功能:
将信号集清空
参数:
指定要清空的信号集
返回值:
成功:0
错误:-1
sigfillset(sigset_t *set)
功能:
将信号集置为满
参数:
set:指定要置满的信号集
返回值:
成功:0
错误:-1
int sigaddset(sigset_t *set, int signum);
功能:
给信号集添加信号
参数:
set:指定信号集
signum:指定添加信号
返回值:
成功:0
错误:-1
int sigdelset(sigset_t *set, int signum);
功能:
删除指定信号
参数:
set:指定信号集
signum:指定删除信号
返回值:
成功:0
错误:-1
int sigismember(const sigset_t *set, int signum);
功能:
测试信号是否为指定信号集成员
参数:
set:指定信号集
signum:指定信号
返回值:
错误:-1
否:0
有:1
设置解除阻塞
设置对2号信号进行阻塞:
1、定义sigset_t block_set信号集
2、将block_set信号集所有成员清空
3、将2号信号添加到block_set信号集中
4、将block_set设置为这个进程的阻塞信号集
如何将信号集设置为阻塞:使用sigprocmask(2)函数,包含头文件#include <signal.h> 。执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending)。
进程可以选择阻塞(Block)某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。注意,阻塞和忽略是不同,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。
int sigprocmask(int how,const sigset_t*set,sigset_t *oldset);
功能:
检测活泼改变阻塞信号
参数:
how:用于指定信号修改的方式,可能选择有三种
SIG_BLOCK//将set所指向的信号集中包含的信号加到当前的信号掩码中。即信号掩码和set信号集进行或操作。
SIG_UNBLOCK//将set所指向的信号集中包含的信号从当前的信号掩码中删除。即信号掩码和set进行与操作。
SIG_SETMASK //将set的值设定为新的进程信号掩码。即set对信号掩码进行了赋值操作。
set:为指向信号集的指针,在此专指新设的信号集,如果仅想读取现在的屏蔽值,可将其置为NULL。
oldset:也是指向信号集的指针,在此存放原来的信号集。可用来检测信号掩码中存在什么信号。
返回值: 成功执行时,返回0。失败返回-1,errno被设为EINVAL。
例:实现对2号信号的阻塞
#include<stdio.h> #include<signal.h> int main(void){ signal_t block; //将block集合清空 sigemptyset(&block); //将2号信号添加到block集合中 sigaddset(&block,SIGINT); //将block设置为阻塞信号集 sigprocmask(SIG_SETMASK,&block,NULL); while(1); return 0; }
1、对阻塞信号解除
信号可以分为可靠信号和不可靠信号,多个相同的不可靠信号(1-31),只会响应一个,其他会丢失。可靠信号(34-64)的每一信号都会被响应。
#include<stdio.h> #include<signal.h> int main(void){ signal_t block; //将block集合清空 sigemptyset(&block); //将2号信号添加到block集合中 sigaddset(&block,SIGINT);//此处为不可靠信号 //将block设置为阻塞信号集 sigprocmask(SIG_SETMASK,&block,NULL); sleep(10); sigprocmask(SIG_UNBLOCK,&block,NULL); return 0; }
2、信号阻塞,查看未决信号
使用sigpending(2)查看
sigpending(2)
#include<signal.h>
int sigpending(sigset_t set);
功能:
检测未决信号
参数:
set:值-结果参数,用于返回进程的未决信号
返回值:
成功:0
错误:-1
例,检测未决信号
#include<stdio.h> #include<signal.h> int main(void){ signal_t b,p; //将b集合清空 sigemptyset(&b); //将2号信号添加到b集合中 sigaddset(&b,SIGINT);//此处为不可靠信号 //将b设置为阻塞信号集 sigprocmask(SIG_SETMASK,&b,NULL); while(1){ sleep(1); sigemptyset(&p); sigpending(&p) //检测信号 int f=sigismember(&p,2); if(f==-1){ perror("sigismember"); return 1; } if(f==0){ printf("no 2\n"); }else{ printf("pending 2\n"); } } return 0; }
int sigsuspend(const sigset_t*sigmask);
五、编写代码实现信号处理函数的继承
略,子进程可以继承父进程的信号处理函数。