您的位置:首页 > 运维架构 > Linux

Linux向进程发送信号及执行信号处理函数的时机

2018-01-23 21:16 736 查看
Linux内核中由于不同原因(例如非法地址、按下Ctrl+C、用户进程系统调用等等)向进程发送信号的函数调用路径最后公用的函数是
send_signal()
,这个函数位于linux-3.13/kernel/signal.c文件中。这个函数接下来的调用链为
complete_signal()->signal_wake_up()->signal_wake_up_state()->wake_up_state()->try_to_wake_up()
函数,从上一篇文章可以知道
try_to_wake_up()
函数做了三件事:将任务重新添加到就绪队列,将运行标志设置为
TASK_RUNNING
,如果被唤醒的任务可以抢占当前运行任务则设置当前任务的
TIF_NEED_RESCHED
标志。

在发生中断时,系统在将中断向量号压入堆栈后,会跳转到
linux-3.13/arch/x86/kernel/entry_32.S
中的
common_interrupt
处运行,其代码如下:

common_interrupt:
ASM_CLAC
addl $-0x80,(%esp) /* Adjust vector into the [-256,-1] range */
SAVE_ALL
TRACE_IRQS_OFF
movl %esp,%eax
call do_IRQ            //调用do_IRQ函数,是个C函数,在此函数中处理中断
jmp ret_from_intr      //从中断返回
ENDPROC(common_interrupt)


其中
do_IRQ()
是个C函数,它先取得对应的中断请求描述符,然后执行该中断请求描述符中的中断处理函数,最后软中断也会在这个函数中运行。执行完
do_IRQ()
函数之后,会跳转到
ret_from_intr
处,之后的执行序列会先检查
TIF_NEED_RESCHED
标志,决定是否进行调度,然后会进行信号的投递,代码如下:

work_pending:
testb $_TIF_NEED_RESCHED, %cl
jz work_notifysig
work_resched:
call schedule
LOCKDEP_SYS_EXIT
DISABLE_INTERRUPTS(CLBR_ANY)    # make sure we don't miss an interrupt
# setting need_resched or sigpending
# between sampling and the iret
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
andl $_TIF_WORK_MASK, %ecx # is there any work to be done other
# than syscall tracing?
jz restore_all
testb $_TIF_NEED_RESCHED, %cl
jnz work_resched

work_notifysig:             # deal with pending signals and
# notify-resume requests
#ifdef CONFIG_VM86
testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
movl %esp, %eax
jne work_notifysig_v86      # returning to kernel-space or
# vm86-space
1:
#else
movl %esp, %eax
#endif
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
movb PT_CS(%esp), %bl
andb $SEGMENT_RPL_MASK, %bl
cmpb $USER_RPL, %bl
jb resume_kernel
xorl %edx, %edx
call do_notify_resume              //在这个函数中进行信号处理函数的执行
jmp resume_userspace


然后在
do_notify_resume()
中会调用
do_signal()
函数执行信号处理程序。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux内核 信号 中断