信号
注意 :这由三张表,block
只能添加修改
,pending
只能获取
, handler
只能修改
基础知识
- 抵达——> 执行 / 忽略
- sigset_t 信号集
- 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作
信号集操作
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
使用这个函数改变某个特定的信号对应的处理方法—— handler 表中的方法
#include<stdlib.h>
void abort(void);
发送特定的信号6) SIGABRT
——终止进程
#include<signal.h>
int raise(int sig);
向当前进程发送指定信号
#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset (sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo);
注意:对sigset_t 生成的变量操作,只是将信号存储在栈上,并没有加进今进程pdb中
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
注意 : 使用这个函数将加入pcb中 ,使用这个函数只能对block表进行修改
how
SIG_BLOCK——添加
SIG_UNBLOCK——删除
SIG_SETMASK——设置
将set
设置进pcb中,将pcb中原有的状态寄存如oset
#include<signal.h>
int sigpending(sigset_t *set);
想要信号存入pending表中,可以先将这个信号阻塞,因为对于阻塞的信号,暂存在pending表中,直到阻塞解除
获取进程中所有 pending 信号
#include <iostream>
#include <sys/stat.h>
#include <signal.h>
#include <unistd.h>
#include<sys/types.h>
#include<fcntl.h>
#include<wait.h>using namespace std;int main()
{printf("%d\n",getpid());sigset_t sig;sigemptyset(&sig);sigaddset(&sig,2);sigprocmask(SIG_SETMASK,&sig,nullptr);while(1){// 将正在处理的信号先将这个位置变成0,如果在处理这个信号的时候来相同信号,就会默认加入pending,默认将这个信号屏蔽sigset_t pending;sigpending(&pending);for(int i=31;i>0;i--){if(sigismember(&pending,i)) printf("1");else printf("0");}puts("");// 获取block列表,观察是否进行屏蔽——无法获取block列表sleep(1);}// signal(2,handler);while(1) ;return 0;
}
#include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
修改handler表对应的方法
函数机制介绍
在处理a信号的过程中,自动将a信号加入block表,直到结束自动恢复
使用举例
#include <iostream>
#include <sys/stat.h>
#include <signal.h>
#include <unistd.h>
#include<sys/types.h>
#include<fcntl.h>
#include<wait.h>using namespace std;void handler(int signum)
{printf("signal: %d\n",signum);while(1){// 将正在处理的信号先将这个位置变成0,如果在处理这个信号的时候来相同信号,就会默认加入pending,默认将这个信号屏蔽sigset_t pending;sigpending(&pending);for(int i=31;i>0;i--){if(sigismember(&pending,i)) printf("1");else printf("0");}puts("");// 获取block列表,观察是否进行屏蔽——无法获取block列表sleep(1);}
}int main()
{struct sigaction act;act.sa_handler=handler;sigemptyset(&act.sa_mask);sigaddset(&act.sa_mask,3);// 将3号信号加入信号集中sigaction(2,&act,nullptr);cout<< getpid()<<endl;while(1) ;return 0;
}
sigaddset(&act.sa_mask,3); // 将3号信号加入信号集中
sigaction(2,&act,nullptr);
说明一下这个代码,意思是将3号信号加入信号集,然后将2号信号方法更新进handler表中,特别注意的是,在检测到2号信号的时候,才会将2,3信号加入block表;只发3号信号,还是像普通信号一样