信号机制(信号屏蔽字,未决信号集在进程的PCB中)
信号四要素:信号编号,信号名称,信号默认执行动作,信号事件。(信号编号和名称:看csdn常用信号一览表)## 标题
信号的5中产生方式:
(1)终端按键产生信号:Ctrl+c(2号信号),Ctrl+z(20),Ctrl+\(3);
(2)硬件异常产生信号:除0操作(8),非法访问内存(11)
(3)kill函数/命令产生信号
kill命令产生信号:kill -SIGKILL pid
kill函数:给指定进程发送信号(不一定杀死)
int kill ( pid_t pid , int sig)
sig: 信号宏名;
pid>0: 发送给指定pid进程;
pid==0: 发送给调用kill所属同一组的所用进程;
pid<0: 发送给指定进程组
pid==-1: 发送给进程有权限发送的系统中所有进程;
信号处理的三种形式:默认动作,忽略信号,捕捉(即用户调用自己的处理函数);(9/19号信号不允许忽略和捕捉,只能执行默认动作)
其中默认动作5种:
(1)Term 终止进程
(2)lgn 忽略信号
(3)core 终止进程,生成core文件(查看进程死亡原因,用域gdb调试)
(4)Stop 停止(暂停)进程
(5)cont 继续运行进程
raise函数:给当前进程发送指定信号。成功0,失败非0.
abort函数:给自己发送异常终止信号。6)SIGABRT,无返回值;
alarm函数:设置定时器, 指定seconds后,内核会给当前进程发送14)SIGALARM信号,默认动作为终止进程。
(每个进程有且只有一个定时器)返回值为上一个alarm的剩余时间或者0.
alarm(1) 可计算程序在1s内的计算数量。
time 命令,time a.out 查看用户程序执行时间。(实际执行时间=系统时间+用户时间+等待时间)
信号集操作函数:(自己set--->影响阻塞信号集---->影响未决信号集合)
sigset_t myset
sigemptyset(&myset) // 清空myset信号集为0
sigfilllset(&myset) //myset全部设置为1
sigaddset(&myset,int signum) //将指定的signum放入myset,即置为1;
sigdelset(*myset,int signum)//将signum移除信号集,即置为0;
sigismember(&myset,int signum)//判断signum是否在myset中;
sigprocmask(SIG_BLOCK,&myset,&oldset) //屏蔽信号,解除信号(SIG_UNBLOCK), myset为1的异或到阻塞信号集中。
sigpending(&pend) //获取未决信号集
信号的捕捉(即调用自己定义的函数来处理信号)
signal(捕捉信号的宏,回调函数):注册回调函数,等信号一触发,内核回去自己调用回调函数;
sigacion(捕捉信号的宏,对信号的各种处理集于结构体(& act),NULL)
参数2:struct sigaction{
sa_handler//回调函数
sa_mask//阻塞信号集
sa_flags//=0默认自动屏蔽本信号
}
sigaction:回调函数执行期间(假设10s),阻塞的常规信号不支持排队,产生的信号最多只记录一次
查看未决信号集(信号发送后,被阻塞住的状态)
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void printped(sigset_t * ped)
{
int i=0;
for(int i=0;i<32;++i)
{
if(sigismember(ped,i)==1)
{
putchar('1');
}
else
{
putchar('0');
}
}
printf("\n");
}
int main ()
{
sigset_t myset,oldset,ped;
sigemptyset(&myset); //清空自定义集合
sigaddset(&myset,SIGQUIT);//给自定义集增加屏蔽信号
sigprocmask(SIG_BLOCK,&myset,&oldset);//将增加的屏蔽信号设置进去信号屏蔽字
while(1)
{
sigpending(&ped);//查看未决信号集
printped(&ped);
sleep(1);
}
return 0;
}
结果:当输入信号时ctr+\,3号信号被置为1
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
^C
00000000000000000000000000000000
00000000000000000000000000000000
^\00010000000000000000000000000000
00010000000000000000000000000000
^\00010000000000000000000000000000
^\00010000000000000000000000000000
00010000000000000000000000000000
00010000000000000000000000000000
^C
signal捕捉信号的简单使用
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
typedef void (*sighandler_t)(int );
void printSIG()
{
printf("--------------catch\n");
}
int main()
{
sighandler_t hander;
hander = signal(SIGINT,printSIG);
if(hander == SIG_ERR)
{
perror("signal error");
exit(1);
}
while(1);
return 0;
}
sigaction捕捉信号的使用
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<unistd.h>
void hander(int signum)
{
printf("siganl:%d is catch\n",signum);
sleep(5);
printf("-------------finish-------------\n");
}
int main()
{
struct sigaction act;
act.sa_handler = hander; //给act定义回调函数
sigemptyset(&act.sa_mask); //给act的信号屏蔽字设置信号屏蔽
sigaddset(&act.sa_mask,SIGQUIT);
act.sa_flags=0;//默认属性,回调函数执行期间,自动屏蔽本信号
int ret = sigaction(SIGINT,&act,NULL); //捕捉信号
if(ret ==-1 )
{
perror("sigaction error");
exit(1);
}
while(1);
return 0;
}
结果:
^Csiganl:2 is catch
-------------finish-------------
^Csiganl:2 is catch
^C-------------finish-------------
siganl:2 is catch