我们写在linux系统环境下写一个程序,唔,"它的功能是每隔1s向屏幕打印'hello world'。"

这时,我们在键盘上按出"Ctrl + C"后,进程会发生什么??

我们清晰地看到,进程已经在我们按出"Ctrl + C"后,进程退出了。那为什么会出现这个现象呢??是什么引发了当前运行的前台进程退出呢?

那么我们也就不卖关子了,"Ctrl +C"是一个组合键,作用就是向当前进程发送2号信号。

那么什么是信号呢?信号是如何产生的呢?进程收到信号后的处理动作又是什么呢?

-----前言


一、认识信号

我们在日常生活中,时常都会与信号打交道。例如,在学校听到铃声,在公路上看到红绿灯,但是如果我们从没有上过学,或者从没有去过公路,我们压根不知道出现眼前这种情况,我们的对应动作是什么。因此,我们对信号的认识在于,"识别信号,行为产生",不仅仅是在于能够看到,能够知道这种情况下,是给我是遇到信号了,并且我还需要知道学校铃声响起,我就该上课或者下课了,红灯亮起,此时就不应该在将脚迈上公路。

为什么进程需要信号呢?

我们从识别信号到行为产生,首先就需要有人告诉你这是什么信号,面对这样的信号你要做出的行为是什么?"这是红绿灯","绿灯行红灯停"。唔,这很符合当下,是你通过学习交通知识得出的,并且你会将其信号翻译成形如上述的形式(如果你仍持有人类该有的理性)。这总比让一位主持交通管理的执行员扯着嗓门、比划着让哪路上的行车停止,哪路上的行车启动的行为要方便很多……

当你使用"Ctrl + C"组合热键时,你如何知道该进程收到了什么样的信号呢?你说,是2号信号(你前文说过)。那如果是"Ctlr+Z"组合键呢?恐怕,你只会抓耳挠腮地喃喃信号此时并非很吃香,因为你并不认识该信号,也就更不会有行为的产生。由此,识别信号其实是有成本的。

进程识别信号的本质,与我们识别信号的行为是一致的—— "识别信号,行为产生"。

Linux中信号宏定义:

/usr/include/bits/signum.h

Linux中的信号集:

kill -l 查看
[1,31]:普通信号
[34,64]:实时信号


二、信号产生

(1)信号产生的方式

键盘发送:

在了解了什么是信号后,我们现如今把目光聚焦到信号是如何产生的问题上来。例如,前文常提的两个组合键 "Ctlr +C" , "Ctrl + Z",Linux命令行就会从键盘上获取这两个组合键,并把它们解释为信号,发送给当前进程。

硬件异常:

我们举例一个除0操作的错误代码,并且用核心转储查看。

core-file + 形成的核心转储的文件

我们知道,该进程执行除0操作时收到了信号8。

如何理解除0错误?

如何理解未初始化指针解引用?

我们对一个未完成赋值指针进行解引用。

软件条件:

系统库中提供一个alarm函数,意为"闹铃"。即,过段时间就会给该进发送14闹铃信号。

程序运行3s后,进程收到alarm信号后退出。

当然软件条件还有管道,例如读端已经关闭,写端一直在写,OS绝不会允许这样浪费资源,因此会向正在运行的写端发送管道信号(SIGPIPE)。

系统调用:

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

当然,我们仍然可以通过系统调用向该进发送信号。这个kill函数你是否见着它很熟悉??这不就是我们在命令行输入的kill + signum + pid嘛? 是的! 命令行解释器的底层就是去调用的这个函数!


三、信号保存与阻塞

前文讲述了信号是如何发送的,信号是如何产生的条件。但事实上,信号产生后,只有接收方接收到了,才能进行之后的"递达",也就是行为产生。因此,当OS向进程发送信号时,该进程怎么知道OS向它发送了信号?OS发送了什么信号呢?

又比如,现在你叫张三,你很不喜欢讲台上的老师,于是乎,你根本不在乎他说什么。那么他"发出的任何信号",都不会被你识别,更别说"递达",即行为产生。由此,如果进程选择不接收OS发送的信号,又该作何处理??

信号相关概念:
1.实际执行信号的动作称为:信号抵达。
2.信号从产生到递达之间的状态:信号未决。
3.进程可以选择阻塞某个信号。
4.被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。

注意:
阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作

信号在内核中的表示:

block: 表示阻塞信号集
pending: 表示接收信号集
handler: 信号集方法

正如前文所述,linux内核中,信号num是一堆宏定义整数。

block、pending集是被设计成一种位图的数据结构!举个unsigend_int的例子,32个比特位表示信号个数可以是[1,32]。0表示阻塞(未接收)信号,1表示未阻塞(接收)信号。每一个pending集的比特位,都与handlers这个数组下标的位置一一对应。handlers数组是一个函数指针数组,里面存放的是每一种信号接收时,行为产生函数的地址。

所以,如果你想要改变一个信号,对应的默认行为,你就只需要将你实现的handlers方法函数的地址,填入到内核数据结构中handlers数组里即可。

四、信号处理

根据前文认识了什么是信号,以及信号的产生,我们可以得出如下的结论:
信号是发给进程的,信号产生于操作系统。

可是,我现在的问题是,当前进程收到信号后,就必须要放下"手头"的事,立马去处理到来的信号嘛?毕竟,当我妈叫现在我吃饭,这是一个信号,但是我现在正在写博客、正在上网课,我可以选择继续写我的博客,继续上我的课,当然我也可以选择立即直接扔掉手中敲打的键盘,也可以立即将那喋喋不休的腾讯会议结束掉,立刻前去吃饭。

由此,我们对于信号的处理似乎有,唔大概三种处理方式:

默认行为、忽视行为、自定义行为。

但是,我妈叫我吃饭了,我们是选择了继续干完当前的事,但是干完这些事之后,我才会去吃饭。因此,接收信号后,并不代表一定要产生行为,可以将它先保存,并在适合的时候进行处理。

那么什么算是合适的适合呢??

这里也不卖关子,内核态返回用户态的时候(这个之后会细谈)!

五、内核态vs用户态

我们知道了信号是发送给进程的,发送方是OS。但是OS是如何发送信号的?我们接收到信号时,该进程是怎么知道的?一定需要到进程的内核数据结构中去,但是我们能去吗?肯定不行!这个行为,只有OS才能帮我们这样做。同样,如果我们需要自定义信号捕捉(信号递达),不是我们去更改那个handler表,因为我们并没有权限!OS不信任任何人!

(1)身份切换

(2)内核地址空间

我们使用库函数时,只区分动态库和静态库。动态库的函数地址会在程序运行时加载进共享区,而使用静态库函数时,函数地址会被编译进源程序中,存储在代码区。

那么我们使用系统调用接口,我们是怎么找到它们的地址并,调用它们的?

总结:

信号产生:

信号抵达:

本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~

Linux小黑板(10):信号相关推荐

  1. linux信号掩码线程,20.10 信号掩码(阻塞信号传递)

    20.10  信号掩码(阻塞信号传递) 内核会为每个进程维护一个信号掩码,即一组信号,并将阻塞其针对该进程的传递.如果将遭阻塞的信号发送给某进程,那么对该信号的传递将延后,直至从进程信号掩码中移除该信 ...

  2. Linux 小程序开发日记(终章)(pyqt+yolov5)

    Linux 小程序开发日记(终章) 哈喽大家好,我是爱喝欢乐水的柳橙汁,这一篇,是最后一篇啦.我会将所有个过程都梳理一遍. 关于代码的详细注释,大家就参考一下之前的笔记吧.这一篇博客我就放上我精简的代 ...

  3. Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存

    Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> ...

  4. “懒惰”Linux 管理员的 10 个关键技巧

    "懒惰"Linux 管理员的 10 个关键技巧 来源:Vallard Benincosa 分享到:更多0 好的系统管理员区分在效率上.如果一位高效的系统管理员能在 10 分钟内完成 ...

  5. 基于busybox的Linux小系统制作 (initrd)

    我们有时候有需要在busybox基础上,制作linux,可是却不知道具体怎么做,这里将对基于busybox的linux小系统制作做出详细的步骤说明. 准备环境: 1.一个Redhat完整系统的虚拟机, ...

  6. 私人定制---打造属于自己的linux小系统

    为什么80%的码农都做不了架构师?>>>    一.前言 linux操作系统至1991.10.5号诞生以来,就源其开源性和自由性得到了很多技术大牛的青睐,每个linux爱好者都为其贡 ...

  7. linux进程中对信号的屏蔽,linux进程中的信号屏蔽

    在linux的进程中可以接收到各种的信号,并且如果你不对信号进行处理,linux中的进程就会采用默认的处理方式处理,比如ctrl-c的信号,进程对它的处理就是终止进程的执行. 在linux中,我们也可 ...

  8. linux的基础知识——信号的四要素和kill

    1.信号的四要素 \qquad信号的名字:信号的编号:信号的默认处理动作:信号的事件 2.信号相关命令 \qquad查看linux下的所有信号:kill -l:查看信号文档:man 7 signal. ...

  9. Android小知识10则(上)(2018.8重编版)

    Android小知识10则(下) 目录 前言 横竖屏锁定 不同分辨率的图标 将字符串写在资源文件中 为AlertDialog设置点击监听 ProgressDialog了解一下 最后 前言 Androi ...

最新文章

  1. Java--23种设计模式之decorator模式
  2. 用unsigned char 表示字节
  3. 拓扑排序杭电 1285确定比赛名次
  4. unet作为服务器不显示画面,UNet:无法生成服务器对象(不使用NetworkManager)
  5. 洛谷 P2286 [HNOI2004]宠物收养场
  6. python html5lib时间_如何使用Python模块 html5lib
  7. O(1) O(n)
  8. 从零基础入门Tensorflow2.0 ----三、6. 实战tf.constant
  9. 在输入框后面提示错误_Q9登录错误?你想要的解决方法都在这!
  10. 背包笔记及Java实现
  11. java并发增强工具_0318 guava并发工具
  12. [LeetCode] 682. Baseball Game 棒球游戏
  13. uva10105(数论多项式展开公式)
  14. 无限火力跳跳机器人_英雄联盟无限火力小拳拳升降机蒸汽机器人
  15. HDU 6438 Buy and Resell【贪心】
  16. 像素与照片尺寸、分辨率之间的关系
  17. tomcat点击startup.bat闪退
  18. android usb采集卡,USB HDMI直播采集卡1805怎么用?
  19. 亚商投资顾问 早餐FM/0607华虹公开发行股票注册
  20. Chrome浏览器插件开发-淘宝自动登录

热门文章

  1. MySQL问题记录(Linux)
  2. 水山破碎锤的五个大特点
  3. 网页设计中的极简主义
  4. TCL联袂爱奇艺,能碰出什么不一样的火花?
  5. KUKA机器人_示教器的基本组成结构和功能介绍
  6. APISIX简介与应用
  7. disabled 属性
  8. 自定义Button形状(圆形、椭圆) shape
  9. 2019/8/26 日常学习的一天
  10. no qualifying bean of type bean的解决方法