关闭

Linux内核中的信号机制——信号处理

发表于:2013-2-25 10:02

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:ce123    来源:51Testing软件测试网采编

  下面具体看看sys_sigreturn()的定义:

asmlinkage int sys_sigreturn(struct pt_regs *regs)
{
 struct sigframe __user *frame;
 sigset_t set;

 /* Always make any pending restarted system calls return -EINTR */
 current_thread_info()->restart_block.fn = do_no_restart_syscall;

 /*
  * Since we stacked the signal on a 64-bit boundary,
  * then 'sp' should be word aligned here.  If it's
  * not, then the user is trying to mess with us.
  */
 if (regs->ARM_sp & 7)
  goto badframe;

 frame = (struct sigframe __user *)regs->ARM_sp;

 if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
  goto badframe;
 if (__get_user(set.sig[0], &frame->sc.oldmask)
     || (_NSIG_WORDS > 1
         && __copy_from_user(&set.sig[1], &frame->extramask,
        sizeof(frame->extramask))))
  goto badframe;

 sigdelsetmask(&set, ~_BLOCKABLE);
 spin_lock_irq(&current->sighand->siglock);
 current->blocked = set;
 recalc_sigpending();
 spin_unlock_irq(&currentt->sighand->siglock);

 if (restore_sigcontext(regs, &frame->sc, &frame->aux))
  goto badframe;

 /* Send SIGTRAP if we're single-stepping */
 if (current->ptrace & PT_SINGLESTEP) {
  ptrace_cancel_bpt(current);
  send_sig(SIGTRAP, current, 1);
 }

 return regs->ARM_r0;

badframe:
 force_sig(SIGSEGV, current);
 return 0;
}

  这个函数主要调用restore_sigcontext()根据用户态态堆栈上的sigframe备份还原pt_regs。

static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
     struct aux_sigframe __user *aux)
{
 int err = 0;

 __get_user_error(regs->ARM_r0, &sc->arm_r0, err);
 __get_user_error(regs->ARM_r1, &sc->arm_r1, err);
 __get_user_error(regs->ARM_r2, &sc->arm_r2, err);
 __get_user_error(regs->ARM_r3, &sc->arm_r3, err);
 __get_user_error(regs->ARM_r4, &sc->arm_r4, err);
 __get_user_error(regs->ARM_r5, &sc->arm_r5, err);
 __get_user_error(regs->ARM_r6, &sc->arm_r6, err);
 __get_user_error(regs->ARM_r7, &sc->arm_r7, err);
 __get_user_error(regs->ARM_r8, &sc->arm_r8, err);
 __get_user_error(regs->ARM_r9, &sc->arm_r9, err);
 __get_user_error(regs->ARM_r10, &sc->arm_r10, err);
 __get_user_error(regs->ARM_fp, &sc->arm_fp, err);
 __get_user_error(regs->ARM_ip, &sc->arm_ip, err);
 __get_user_error(regs->ARM_sp, &sc->arm_sp, err);
 __get_user_error(regs->ARM_lr, &sc->arm_lr, err);
 __get_user_error(regs->ARM_pc, &sc->arm_pc, err);
 __get_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err);

 err |= !valid_user_regs(regs);

#ifdef CONFIG_IWMMXT
 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
  err |= restore_iwmmxt_context(&aux->iwmmxt);
#endif
#ifdef CONFIG_VFP
// if (err == 0)
//  err |= vfp_restore_state(&aux->vfp);
#endif

 return err;
}

  restore_sigcontext()很简单,当它返回后,通过sys_sigreturn()在内核态堆栈建立的pt_regs已经变为调用信号处理函数之前的pt_regs。这样,sys_sigreturn()返回用户态时,就顺利地过渡到处理之前的状态了。

相关链接:

Linux内核中的信号机制——一个简单的例子

Linux内核中的信号机制——信号发送

55/5<12345
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号