信号是怎么产生的?
1.按键产生:如:Ctrl+c、Ctrl+z、Ctrl+
2.系统调用产生,如:kill、raise、abort
3.软件条件产生,如:定时器信号alarm
4.硬件异常产生,如:非法访问内存(段错误)、除数为0(浮点型例外)、内存对齐出错(总线错误)
5.命令产生,如Kill命令
信号的特点:
简单、不能携带大量信息、特定条件下产生。
如进程1给进程2发送了一个信号,进程2就会暂停目前的操作,转而去处理这个信号,属于一个软中断,
信号属于异步事件,进程1给进程2发了一个信号,不用等进程2的响应,可以继续执行其他的操作。
信号的两种状态:
递达:递达并到达进程
未决:产生和递达之间的状态,主要用于阻塞(屏蔽)导致此状态
未决信号集:
1.信号产生,未决信号集中描述该信号的位立刻翻转为1,表明信号处于未决状态,当信号被处理对应位被翻转为0,这一时刻往往非常短暂
2.信号产生后如果有其他原因(一般是阻塞)导致信号不能抵达,在屏蔽解除到达前,未决信号集对应这个时间的位一直是1,处于未决状态
阻塞信号集:
他就是未决信号集前的一堵墙,信号会先辈设置了的堵塞信号集给挡住,这时候未决信号集对应位置给设置成1,什么时候不堵塞,未决信号集才能处理信号,使得对应位翻转成0.
信号的处理方式:
1.执行默认动作
2.忽略(丢弃)
3.捕捉(调用用户自己定义的处理信号函数)
(可在linux终端下使用man 7 signal查看信号执行的默认动作)
//可以看到默认动作有以下五种:Term(终止)、lgn(忽略)、Core(终止并且产生core文件)、Stop(暂停)、Count(继续)这五种默认动作,其中9号(SIGKILL)跟19号(SIGSTOP/SIGCONT)这两信号不能捕捉,不能忽略,甚至不能阻塞
既然KILL命令能产生信号,那我们就先来实战一番KILL命令的实战,实践才能进步
先看KIILL函数的一些小解释:
int kill(pid_t pid,int sig);
/*pid大于0,要发送进程ID
pid=0,代表当前调用系统进程组内所有进程
pid=-1 代表有权发送所有的进程
pid<0,代表-pid对应的组内所有进程
sig对应的信号*/
运行结果如下图:5秒后子进程获取到父进程的pid号,然后杀死了父进程
我们通过ps aux 命令查看,可以看到子进程还在运行。
详细代码如下:
#include<stdio.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>//这两头文件可以通过man 2 kill命令查看,是kill命令所需要的
#include<signal.h>
int main()
{
int i;
for(i=0;i<5;i++)
{
pid_t pid=fork();
if(pid==0){
break;
}
}
if(i==2)
{
printf("I will kill father after 5s\n");
printf("我的pid号是%d\n",getpid());
sleep(5);
kill(getppid(),SIGKILL);//获取到父进程的pid并杀死父进程
while(1){
sleep(1);
}
}
else if( i==5 )
{
while(1){
printf("I am parent, I am happy\n");
sleep(1);
}
}
return 0;
}
更深入的实战可以看链接:链接: https://blog.csdn.net/weixin_42569526/article/details/107855647.