趣谈 Linux 操作系统
刘超
前网易杭州研究院云计算技术部首席架构师
85459 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 72 讲
趣谈 Linux 操作系统
15
15
1.0x
00:00/00:00
登录|注册

38 | 信号(下):项目组A完成了,如何及时通知项目组B?

出现在很多涉及信号和信号处理的地方
从rt_sigreturn返回用户态
调用rt_sigreturn再次进入内核
调用sa_restorer恢复原程序执行位置
设置pt_regs和栈帧
调用handle_signal处理信号
调用do_signal处理信号
设置_TIF_SIGPENDING标识位
tkill或tgkill发送信号给线程
kill或sigqueue系统调用
kill命令
子进程退出时发送SIG_CHLD信号
向读端已关闭的管道写数据产生SIGPIPE信号
进程访问非法内存产生SIGSEGV信号
执行除以0的指令产生SIGFPE信号
Ctrl+Z产生SIGTSTP信号
Ctrl+C产生SIGINT信号
规律
信号处理函数执行完毕后返回用户态
信号处理函数
从系统调用或中断返回时处理信号
直接发送信号的方法
内核发送信号
硬件异常产生信号
终端输入组合键
查找signal_pending出现的地方
信号的处理
信号的发送
课堂练习
信号的发送与处理

该思维导图由 AI 生成,仅供参考

信号处理最常见的流程主要是两步,第一步是注册信号处理函数,第二步是发送信号和处理信号。上一节,我们讲了注册信号处理函数,那一般什么情况下会产生信号呢?我们这一节就来看一看。

信号的发送

有时候,我们在终端输入某些组合键的时候,会给进程发送信号,例如,Ctrl+C 产生 SIGINT 信号,Ctrl+Z 产生 SIGTSTP 信号。
有的时候,硬件异常也会产生信号。比如,执行了除以 0 的指令,CPU 就会产生异常,然后把 SIGFPE 信号发送给进程。再如,进程访问了非法内存,内存管理模块就会产生异常,然后把信号 SIGSEGV 发送给进程。
这里同样是硬件产生的,对于中断和信号还是要加以区别。咱们前面讲过,中断要注册中断处理函数,但是中断处理函数是在内核驱动里面的,信号也要注册信号处理函数,信号处理函数是在用户态进程里面的。
对于硬件触发的,无论是中断,还是信号,肯定是先到内核的,然后内核对于中断和信号处理方式不同。一个是完全在内核里面处理完毕,一个是将信号放在对应的进程 task_struct 里信号相关的数据结构里面,然后等待进程在用户态去处理。当然有些严重的信号,内核会把进程干掉。但是,这也能看出来,中断和信号的严重程度不一样,信号影响的往往是某一个进程,处理慢了,甚至错了,也不过这个进程被干掉,而中断影响的是整个系统。一旦中断处理中有了 bug,可能整个 Linux 都挂了。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了信号的发送与处理过程,重点介绍了信号处理的两个主要步骤:注册信号处理函数和发送信号以及处理信号。文章首先提出了信号处理最常见的流程主要是两步,然后详细讲解了注册信号处理函数的内容。接着,文章引出了一个问题:一般什么情况下会产生信号呢?并表示将在接下来的内容中进行探讨。通过这样的引出,读者可以对接下来的内容产生期待,增加了阅读的吸引力。 文章详细介绍了信号的发送方式,包括通过终端输入组合键、硬件异常以及内核发送信号等多种情况。针对不同的发送方式,文章分析了信号的处理机制,包括信号的可靠性和不可靠性,以及信号处理函数的调用时间不确定性等方面。此外,文章还解释了信号的处理与进程调度的相似之处,以及信号处理过程中的标识位设置和唤醒机制。 通过深入的技术分析,本文为读者提供了对信号发送与处理过程的全面了解,对于从事相关领域的技术人员具有一定的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《趣谈 Linux 操作系统》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(29)

  • 最新
  • 精选
  • 江山未
    感觉看的过程中,我的大脑不断的发出"我看不懂"的中断,让我不断的的从"认真态"返回到"涣散态"。随后执行启动时注册的看不懂处理函数"逼自己看"后,才重新进入"认真态"(并不能)。

    作者回复: 赞,很生动,加油

    2019-08-15
    3
    31
  • 韩俊臣
    能把这么复杂的调用链讲的这么生动,大写的服

    作者回复: 谢谢

    2020-06-12
    4
  • chengzise
    老师好,文章的信号处理流程是在程序进入系统调用后接收到信号的情况。希望老师补充一下,程序没有进入系统调用(一个简单的死循环程序),此时接收到系统信号会走什么样的流程。谢谢。

    作者回复: 差不多的

    2019-06-25
    2
    2
  • 刘強
    老师,既然内核态对用户态的栈随意操作(果然是内核,权利就是大),但返回的时候还是保持系统调用前的样子,丝毫没有察觉背后发生了这么多事情,就好像调用了一个普通用户态的函数一样,那么我在用户态调试程序的时候,能否看到这种内核对用户栈的修改?

    作者回复: 不能,调试也是靠信号

    2019-06-24
    1
  • 饭粒
    梳理的真清楚。

    作者回复: 谢谢啦

    2019-08-06
  • humor
    老师,我突然想到了一个稍微无关的问题想请教一下。就是linux的安全问题,现在基本服务器上使用的操作系统都是linux,而安装linux只是下载一个系统镜像就可以安装了,但是,我们怎么能相信我们下载的linux镜像肯定没有安全问题呢,比如发布方安装了恶意程序或者开了一个后门之类的。我想了解一下一般的云服务厂商是怎么检测这类操作系统或者更加底层的硬件的安全问题的呢?

    作者回复: 有安全硬件,还有安全操作系统的,不过还是要相信linux

    2019-06-25
    3
  • 安排
    能把这个流程串起来,老师功力深厚啊
    2019-06-24
    1
    52
  • 欢乐小熊
    Linux 信号通信主要由如下几个步骤组成 - 信号处理函数的注册 - 信号处理函数的注册, 定义在用户空间 - 注册最终通过 rt_sigaction 系统调用发起 - 将用户空间定义的信号处理函数保存到 task_struct 中 sighand 的 action 数组中 - 信号的发送 - 信号的发送通过 kill/tkill/tgkill/rt_sigqueueinfo 函数执行 - 最终通过 __send_signal, 将这个信号添加到对应 进程/线程 的信号待处理链表中 - < 32 为不可靠信号, 待处理列表中存在该信号, 则会自动忽略 - >= 32 为可靠信号, 同一个信号会被添加到信号队列中 - 信号的处理 - 信号的处理会在系统调用或中断处理结束返回用户空间的时机通过 exit_to_usermode_loop 中的 do_signal 执行 - 修改用户函数栈, 插入我们构建的信号处理函数的栈帧 rt_sigframe, 并且将原来的函数栈信息保存在 uc_mcontext 中 - 信号处理函数执行结束之后, 会通过系统调用 rt_sigreturn 恢复之前用户态栈
    2019-06-24
    13
  • 小龙的城堡
    这一章讲得非常棒!很清晰!感谢老师!
    2019-06-24
    1
    5
  • 徐少文
    看了后面的图一下子就茅塞顿开了,一边感叹Linux内核设计的精妙,一边觉得老师功力深厚
    2021-09-16
    4
收起评论
显示
设置
留言
29
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部