Linux kernel 分析之十一:信号通信

本文详细介绍了Linux内核中的信号通信,特别是struct rt_sigframe的结构及其在信号处理中的作用。通过设置用户进程堆栈,内核使得信号处理程序能够执行,并在完成后使用__kernel_rt_sigreturn进行“善后”。在信号处理结束后,进程状态得以恢复,继续执行之前的代码。
信号是进程之间通信的一种方式。它包括3部分操作:
1.设置信号处理函数。系统调用signal。内核调用sys_signal(),设置当前进程对某信号的处理函数。
2.发送信号.系统调用kill。内核调用sys_kill()。向目标进程发送信号。3.接收并处理信号。目标进程调用do_signal()处理信号。
从用户态的角度看,目标进程在执行用户态的代码时突然“中断”,转而去执行对应的信号处理函数(同样在用户态)。等到信号处理函数执行完后,又从原来被中断的代码开始执行。
如何达到这样的效果呢?由前面的几种内核的伪装现场的手段,我们可以猜出它这次使用的手段。比如,要让目标进程执行信号处理函数,在内核态中当然不可能直接调用,但是可以通过设置pt_regs中的eip来达到这种效果。但是,要使目标进程在执行完信号处理函数后,又恢复到被中断的现场继续执行,那得花些技巧。不过,不外乎设置堆栈。这一次还包括了用户态堆栈。由于恢复的任务比较艰巨,系统干脆提供了一个系统调用sigreturn 。
既然内核希望用户在执行完信号处理函数后,调用sigreturn。接下去的思路就比较简单了。就是先把用户态的eip设置为signal_handler(通过修改pt_regs中的eip来实现),然后把堆栈中的返回地址改成调用sigreturn的一段代码的入口(当然原来的返回地址也还是要保存的)并且把相关参数“压入”用户态堆栈。
这样,在源进程发送信号后不久,目标进程被调度到,然后执行到do_signal。对信号一一作处理。调用顺序:
do_signal()->handle_signal()->setup_rt_frame()用来设置用户态堆栈。
我们看看这个函数做了些啥?
447         frame = get_sigframe(ka, regs, sizeof(*frame));
struct rt_sigframe __user *frame是内核在用户态的堆栈上新分配的一个数据结构。

011 struct rt_sigframe

012 {

013   &

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值