33 信号入门

重点

1.掌握linux信号的基本概念
2.掌握信号产生的一般方式
3.理解信号递达和阻塞的概念,原理
4.掌握信号捕捉的一般形式
5.重新了解可重入函数的概念
6.了解竞态条件的情景和处理方式
7.了解SIGCHLD信号,重新编写信号处理函数的一般处理机制

目录

1.概括
2.概念
3.信号分类
4.信号的处理方式
5.自定义行为

概括

信号部分大致分为下面四个部分
在这里插入图片描述

概念

信号的例子:信号弹,下课上课铃声,红绿灯,快递发短信,发令枪,哨子,闹钟,外卖电话,冲锋号

需要知道的内容

a.怎么认识例字里这些信号的,有人教然后记住了
认识信号,包括识别信号,知道信号的处理方法。记住了常见的信号
b.即使是没有信号产生,我们也知道信号发生后该干什么
c.信号产生了,可能不立即处理,可能正在做更重要的事情,在合适的时候再处理。所以在产生信号,时间窗口,处理信号前,在这个时间窗口内都必须记住这个信号来了

结论

1.进程必须能够识别+处理信号,信号就算没有产生,也有具备识别和处理的能力,信号的处理属于进程内置功能的一部分
2.进程即便没有收到信号,也能知道哪些信号该怎么处理
3.当进程真的收到了一个具体的信号的时候,进程可能并不会立即处理这个信号
4.一个进程必须当信号产生,到信号开始处理,就一定会有时间窗口,进程具有保存哪些信号已经发生了的能力

生活角度的信号

在网上买了很多件商品,再等待不同商品快递的到来,但即使宽邸没有来,也知道快递来临时,该怎么处理快递,也就是“识别快递”
当快递员到了楼下,也收到了快递的通知,但正在打lol团战,5min后才能取快递。那么在5min内,并没有下去取快递,但是知道有快递来了,也就是取快递的行为不一定要立即执行,可以理解为“在合适的时候去取”
在收到通知,再到你拿到快递期间,是有一个时间窗口的,在这段时间,并没有拿到快递,但是知道有一个快递来了,本质就是“记住有一个快递要取”
当时间合适,拿到快递就开始处理。一般有三种方式:1.执行默认动作,打开使用 2.执行自定义动作,如送给别人 3.忽略快递,继续下一把游戏

技术角度的信号

前台和后台

在xshell运行一个死循环程序
在这里插入图片描述

当这个程序运行的时候,输入什么命令都不管用,这就是前台进程。这个程序一运行,bash就不会接收键盘命令了。按crtl+c可以杀死这个前台进程

运行的时候加个取地址,就代表后台运行,这时候输入命令可以正常执行
在这里插入图片描述在这里插入图片描述

这时候输入crtl+c无法杀死这个后台进程
后台进程可以启动多个,不会影响bash接收命令,只不过命令回显会打印出来,是多个进程共同访问显示器这个共享资源,但没有保护,才出现这种情况

总结
一次登录中,一个终端,会配上一个bash,每一个登录,只允许一个进程是前台进程,可以允许多个进程是后台进程。前后台进程的区分是谁能获取键盘输入

crtl c

用户输入命令,在shell下启动一个前台进程
用户按下crtl+c组合键,输入产生一个硬件中断,被os获取,解释成信号,发送给目标前台进程,前台进程因为收到信号,引起进程退出

操作系统就是我们,信号就是快递的短信,收到短信取快递就是操作系统收到信号结束了进程

注意
1.crtl+c产生的信号只能发给前台进程,一个命令后面加个&可以放到后台运行,这样shell不必等待进程结束就可以接受新的命令,启动新的进程
2.shell可以同时运行一个前台进程和任意多个后台进程,只有前台进程才能接到像crtl+c这种控制键产生的信号
3.前台进程在运行过程中用户随时按下crtl+c产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到SIGINT信号而终止,所以信号相对于进程的控制流程来说是异步(Asyncchronous)的

概念

信号是进程之间事件异步通知的一种方式,属于软中断

信号分类

kill -l 查看所有信号

在这里插入图片描述

每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,crtl+c就是2号信号,#define SIGINT 2

1-31是普通信号,34以上是实时信号,我们只讨论普通信号

信号的处理方式

看到红灯时,一般情况下会停下来,有的人可能会忽略红灯继续行走,也可以有其他行为,唱歌等
对于信号:
1.默认处理
2.忽略
3.自定义动作,提供一个信号处理函数,要求内核在处理该信号时切换到用户态去执行这个处理函数,这种方式也称为捕捉(Catch)一个信号

自定义行为

如何验证crtl+c是收到了2号新号,可以对2号信号进行捕捉,自定义行为,再次crtl+c看会不会执行自定义动作

signal函数
在这里插入图片描述
这个函数可以对传入的信号编号自定义处理方式,第二个参数是一个void的函数指针
用下面代码测试:

#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <signal.h>

using namespace std;
void myhandler(int signal)
{
    cout << "get a singal" << signal << endl;
}

int main()
{
    signal(SIGINT, myhandler);
    while (true)
    {
        //printf("hello world\n");
        sleep(1);
    }
}

运行后输入crtl+c会变为输出函数里的内容
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值