2014年8月3日 信号处理程序调用过程
当一个进程接收到一个信号时,需要暂停进程执行转去执行专门的信号处理函数(如果定义了这个信号的专门处理函数的话),然后再继续执行进程代码。
所有的信号处理都是通过内核函数do_signal进行的,do_signal如果发现需要处理的信号,并且这个信号有专门的处理函数,就需要调用这个用户态的函数,这是通过handle_signal来处理的。执行信号处理函数是非常复杂的任务,因为在用户态和内核态来回切换需要特别谨慎地处理栈里的内容,在当前进程恢复“正常”执行前,首先需要执行用户态的信号处理函数。此外当内核打算恢复进程的正常执行时,内核态堆栈不再包含被中断程序的硬件上下文,因为每当从内核态到用户态转换时,都会清空内核栈的内容。另外一个复杂性是因为信号处理程序可以调用系统调用,在这种情况下,在执行了系统调用后,必须回到信号处理程序而不是到被中断程序的正常代码。
内核采用的解决方法是把保存在内核态中的硬件上下文拷贝到当前进程的用户态堆栈中。当信号处理程序结束时,自动调用sigreturn()系统调用把这个硬件上下文恢复到内核态堆栈中。
先来看个图: