linux 2.4内核之信号(二)
时间:2007-06-16 来源:yjfpb04
linux 2.4内核之信号(二)
赶紧写完.过了那么多天.再不记点.以后更懒得动了.
主要是do_signal() > handle_signal() > setup_frame()函数
一般进程是从用户空间进入系统空间.返回时发现有信号要处理.即返回到用户空间的处理程序.然后再进入系
统空间.返回到一开始的用户空间.
这里重要的就是要保存一开始的用户空间进入时的系统堆栈的frame.这样才能返回到一开始的用户空间
要保存这个frame,由于一个进程的系统空间堆栈是有限的.(一般8k).所以最好保存到用户空间堆栈.
1.设置返回到信号处理程序的用户空间堆栈.从一开始的用户空间进入系统空间时,保存有struct pt_regs-
>regs结构.里面的regs->esp就是一开始的用户空间堆栈,regs->eip返回时要执行的程序地址.当然还有一些
其它的寄存器.要返回到处理程序就要改变regs,通过设置regs->esp使其多一个sigframe(保存一开始的regs
在其中),这样返回处理程序的用户空间基本设置好.
2.使处理程序运行完又进入系统空间.专门设置了一个系统调用sys_sigreturn().由于我们设置的处理程序的
用户空间堆栈时,最上面的是sigframe结构.所以信号处理程序运行完.把这里当成函数的返回地址.具体就是
sigframe结构中的pretcode.而在设置sigframe时,pretcode是retcode[]的地址.所以执行retcode中的代
码.里面有三条指令.
pop %eax
movl $__NR_sigreturn,%eax
int $0x80
所以这样又再进入的系统空间.
3.再进入系统空间时,由于堆栈指针调整了8个字节(4字节返回地址+pop %eax),所以regs->esp-8才是
sigframe结构了..
然后即把sigframe结构中的相关的拷到regs中.从而实现了返回一开始的用户空间.
当然这里还要设置当前信号的block.因为处理时,当然信号被屏蔽.在这里把它恢复
4.关于为什么一定要设置系统调用,而不直接把一开始的返回地址,放在信号处理程序的返回地址.
因为这样不能够保存会自动保存寄存器.当信号处理程序改变寄存器时.则会发生混乱.而通过系统调用
则会自动保存