[ULK11]信号(三):从信号传递到原程序恢复执行


背景:内核刚刚处理完中断和异常.现在它要返回到@current进程了.然而,在返回以前,内核总会习惯性检查一下@current的TIF_SIGPENDING标志,以便确定是否有尚未处理的信号.很不幸,确实有信号正在挂起队列上排队.于是,内核开始启动do_signal()函数…


一. do_signal()函数

遍历@current的挂起信号队列:
1.如果信号的传递方式是SIG_IGN,则忽略这个信号;
2.如果信号的传递方式是SIG_DFL,则根据具体的信号执行相应的默认操作;
3.如果信号有一个处理函数,终止遍历,执行这个信号处理函数;
4.如果信号是0,则检查并处理系统调用的重新执行.
信号处理函数或系统调用的重新执行会返回到内核.紧接着,当内核尝试恢复原程序的执行时,又会陷入do_signal()函数.最终结果是,do_signal()将处理挂起信号队列中的每一个信号.

1.参数

  • regs 栈,current在用户态下寄存器的内容存于此处
  • oldset 阻塞信号的位掩码数组(已被删除)

2.说明

1. 通常只在CPU返回到用户态时才调用此函数:TIF_SIGPENDING标志的检查总是在内核准备返回到用户态时进行.
2. 反复调用dequeue_signal()直到pending和shared_pending队列为空
3. 调用栈

  • do_signal()
    在返回到用户态前,处理@current的每一个未阻塞的挂起信号.
    • get_signal_to_deliver()
      遍历挂起信号队列,自行忽略信号或为信号执行默认操作.
    • handle_signal()
      为执行信号处理程序做准备.
      • setup_rt_frame()
        复制,修改@current的硬件上下文.

3.复杂性

  • 竞争条件,冻结系统,产生内存信息转储,停止/杀死整个线程组
  • 中断处理程序调用此函数(可能性?)
  • 当current正受到其他进程监控的时候怎么办?
    do_notify_parent_cldstop()和schedule()
  • 待处理的信号是一个被忽略的信号(可能性?)
  • 待处理西信号需要被执行缺省操作
  • 待处理信号有一个信号处理函数

二.get_signal_to_deliver()函数

这个函数遍历挂起信号队列,处理被显式忽略的信号并并为具体信号执行相应的默认操作.如果遇到信号0(处理系统调用的重新执行)或者遇到注册了信号处理程序的信号,则终止遍历,返回到do_signal()

1.函数的执行过程

  • try_to_freeze()
    linux冻结系统在信号系统中的钩子函数.linux冻结系统利用信号系统完成自己的功能.
  • if(signal->flags & SIGNAL_CLD_MASK)
    每一个停止的进程在苏醒后都会运行这个检查.在这里,我们检查一下是不是需要通知@current的父进程
  • 陷入一个无限循环
    • 在循环的开始,检查是不是需要停止整个线程组.
    • 从挂起队列上摘下一个信号
    • 如果信号是0,则返回0
    • 如果信号被显式忽略,continu
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值