信号产生前
文章目录
信号与信号量完全没有任何关系
信号入门
生活中还有没有信号的场景呢?
:闹钟,烽火台的烽火,鸡鸣声。。。—》都是给人看的
当我们面对这些场景的时候,我们就立马能够想到某些东西的时候,这些都是信号
信号的产生就代表上面的场景触发,
信号的产生—》信号是要给进程发的—》进程要在合适的时候,要执行对应的动作
但是,并不是这些场景真正放在我面前的时候,我才知道应该怎么做,这些场景是否被触发,没有直接的关系
因为对于信号的处理动作,我们早就知道了,甚至远远早于信号的产生
如:听的铃声响了,我们就知道下课了
我们怎么做到 呢?
我们对特定事件的反应,这是被教育的结果(本质是:我们这些都记住了)
- 所以进程在没有收到信号的时候,进程知道如何识别是什么信号,怎么处理这些信号
而之前在写OS 的时候,程序员就已经设置好了
进程具有识别信号并且处理信号的能力,远远早于信号的产生
在生活当中,我们收到某种信号的时候,并不一定被立即处理(因为信号随时都能产生,但是我当前可能做着更重要的事情,不去处理)
进程收到某种信号的时候,并不是立即处理的,而是在合适的时候才去处理,
进程收到信号之后,需要先将信号保存起来,以供在合适的时候进行对信号的处理
我们把这个信号放在进程 的PCB 里面,所以信号本质也是数据
信号的发送—>往进程task_struct 里面写数据task_struct 是一个内核数据结构,定义进程对象,内核不相信任何人,只相信自己!只有OS 可以往task_struct 里面写入数据(无论我们的信号如何发送,本质上都是在底层通过 OS.进行传输的)
信号产生的各种方式(信号产生前)
demo
kill -l可以查看信号列表
前31个信号是常规信号,后31个是实时信号
键盘ctrl+c的时候,本质上就是我们向进程里面发送2号信号SIGINT
signal
signal:可以修改进程对信号的默认处理工作
第一个参数就是我们的信号对应的宏值,我们既可以使用kill -l信号前面的数字,也可以使用宏
typedef void (*sighandler_t)(int);
函数指针,返回值为void,参数为int
1 |
|
我们发现我们ctrl c 或者kill 2 的话都会处理我们自己对信号的处理
我们发现信号的产生方式其中一种是通过键盘产生的
但是键盘产生的信号只能终止前台进程,不能处理后台进程,只能杀掉前台进程
但是我们可以
1 |
|
杀掉后台进程
信号处理方式概述
总结:
一般而言,收到信号的处理方式有3种
默认动作:终止自己(ctrl c)暂停(ctrl z)等
忽略动作:是一种信号处理的方式,只不过动作就是什么也不干,
(信号的捕捉)自定义动作:类似我们刚刚用signal方法,就是在修改信号的处理动作,有:默认–》 自定义动作,我们可以对不同的信号设置不同的响应动作
1 |
|
9号信号无法被捕捉
信号产生的方式
1
我们通过键盘对进程发送信号
ctrl c ,ctrl d, ctrl z
2
程序中存在异常问题,导致我们收到信号退出
进程崩溃的时候我们最想知道什么
当然是崩溃的原因,我收到了信号,waitpid(),status可以获取退出信号
我要解决他
崩溃的话就可以用这个方法去运行
我们得知道在哪一行崩溃了
- 在linux中当一个进程退出的时候,他的退出码和退出信号都会被设置(正常情况下)
- 当一个进程异常退出的时候,进程的退出信号会被设置,表面当前进程退出的原因
- 如果必要,OS 会设置退出消息中的core dump标志位,并将进程在内存中的数据传输到磁盘当中,方便后续调试
默认情况下在云服务器上core dump是被关掉的
我们这个core dump放开
ulimit -c 10240
放开之后会产生core dump文件
如果进程异常退出的时候,被core dump设置为1
不一定是所有信号都会被core dump
11号信号SIGSEGV
1 |
|
SIGSEGV段错误—-》进程崩溃是因为接收到了11号信号而崩溃的,
8号信号SIGFPE
1 |
|
浮点数错误
在win or linux下进程崩溃的本质是进程收到了对应的信号,然后进程处理信号的默认动作(杀死进程)
但是为什么会收到信号呢?
3
kill
给别人发信号
通过系统调用产生信号
可以向特定进程发送特定信号
1 |
|
raise
给自己发信号
1 |
|
4
通过软件条件,也能产生信号
alarm相当于一个闹钟
在seconds秒之后给我们发送一个14号信号
返回值为0,或剩余的秒数
1 |
|
永远都是操作系统发送的信号
那么我们怎么理解OS给进程发送数据,task_struct -—->本质是,OS向执行进程的task_struct 中的信号位图写入比特位1,即完成了信号的发送–>信号的写入
信号的编号是有规律的[1,31]
1 |
|
我们用什么数据变量来标识是否收到了信号,
uint32_t sigs:一定会存在位图结构
0000 0000 0000 0000 0000 0000 0000 0000
我们认为左大,右边第一个是第一个比特位,
所谓的比特位的位置(第几个),代表的就是哪一个信号,比特位的内容(0,1)代表的就是是否收到了信号
0000 0000 0000 0000 0000 0000 0000 0101
当前进程收到了1号信号,3 号信号,
在进程中采用位图,来标识该进程是否收到信号,