Chinaunix首页 | 论坛 | 博客
  • 博客访问: 665744
  • 博文数量: 156
  • 博客积分: 4833
  • 博客等级: 上校
  • 技术积分: 1554
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-21 19:36
文章分类

全部博文(156)

文章存档

2016年(2)

2013年(1)

2012年(13)

2011年(30)

2010年(46)

2009年(29)

2008年(23)

2007年(12)

分类: BSD

2011-12-14 15:23:46

进程
struct proc
{
   sigqueue_t    p_sigqueue;    /* (c) Sigs not delivered to a td. */
}
线程
/*
 * Kernel runnable context (thread).  This is what is put to sleep and reactivated.
 * Thread context.  Processes may have multiple threads.
 */
struct thread
{
   sigqueue_t    td_sigqueue;
}

信号进程与线程
//if  td == NULL 就是进程级
int tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)

{
     if (td == NULL) {
             td = sigtd(p, sig, prop);
             sigqueue = &p->p_sigqueue;
         } else {
             KASSERT(td->td_proc == p, ("invalid thread"));
             sigqueue = &td->td_sigqueue;
         }
}

信号处理函数进入前,内核构造栈帧与寄存器
with SA_SIGINFO
以Mips为例
寄存器设置:

Linux:
    setup_rt_frame
    {
       ......
       /*
       * Arguments to signal handler:
       *
       *   a0 = signal number
       *   a1 = 0 (should be cause)
       *   a2 = pointer to ucontext
       *
       * $25 and c0_epc point to the signal handler, $29 points to
       * the struct rt_sigframe.
       */
      regs->regs[ 4] = signr;
      regs->regs[ 5] = (unsigned long) &frame->rs_info;
      regs->regs[ 6] = (unsigned long) &frame->rs_uc;
      regs->regs[29] = (unsigned long) frame;
      regs->regs[31] = (unsigned long) frame->rs_code;
      regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;

       ......
    }

Linux: mips执行路径
    (entry.s)work_pending=>
            andi    t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
            beqz    t0, work_notifysig
work_resched:
            jal    schedule

            local_irq_disable        # make sure need_resched and
                    # signals dont change between
                    # sampling and return
            LONG_L    a2, TI_FLAGS($28)
            andi    t0, a2, _TIF_WORK_MASK    # is there any work to be done
                    # other than syscall tracing?
            beqz    t0, restore_all
            andi    t0, a2, _TIF_NEED_RESCHED
            bnez    t0, work_resched
        work_notifysig=>
            move    a0, sp
            li    a1, 0
            jal    do_notify_resume    # a2 already loaded
            j    resume_userspace

           //对比一下各个参数由来
           asmlinkage void do_notify_resume(struct pt_regs *regs,    //a0
                                               void *unused,           //a1
                                              __u32 thread_info_flags) //a2
     {
       /* deal with pending signal delivery */
        if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
        do_signal(regs);
     }


BSD:
   void   sendsig()
    {
        ......
        td = curthread;
        p = td->td_proc;
        PROC_LOCK_ASSERT(p, MA_OWNED);
        sig = ksi->ksi_signo;
        psp = p->p_sigacts;
        mtx_assert(&psp->ps_mtx, MA_OWNED);

        regs = td->td_frame;
        oonstack = sigonstack(regs->sp);
        ......
        regs->a0 = sig;
        regs->a2 = (register_t)(intptr_t)&sfp->sf_uc;
      if (SIGISMEMBER(psp->ps_siginfo, sig)) {
        /* Signal handler installed with SA_SIGINFO. */
        regs->a1 = (register_t)(intptr_t)&sfp->sf_si;
        /* sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; */

        /* fill siginfo structure */
        sf.sf_si.si_signo = sig;
        sf.sf_si.si_code = ksi->ksi_code;
        sf.sf_si.si_addr = (void*)(intptr_t)regs->badvaddr;

     }

     //调用过程
     struct sysentvec elf64_freebsd_sysvec = {
     ......
     .sv_sendsig    = sendsig
     ......
     }
     //正常路径
     mips:asm.h:
         #define DO_AST
           ....
           PTR_LA    s0, _C_LABEL(ast) //ast function
           ....
       
     Mips:exception.S 
       MipsUserGenException=>DO_AST
       MipsUserIntr=>DO_AST
     Mips:switch.S//不重要
        fork_trampoline=>DO_AST

        void  ast(struct trapframe *frame)=>postsig()
         // 
        fork_trampoline在cpu_fork函数中被赋给了
        pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline;
        这个参数会再switch.S被引用
        RESTORE_U_PCB_CONTEXT(ra, PREG_RA, a0)
        .....
        j    ra
        fork_trampoline=>fork_exit(不返回),
        正常情况下不会查信号,进程推出时从fork_exit返回  fork_trampoline 会check一次。
 

     //另一条路径。
      sigsuspend=>kern_sigsuspend=>
      postsig=>(*p->p_sysent->sv_sendsig)(action, &ksi, &returnmask);==sendsig

     
    
阅读(1157) | 评论(0) | 转发(0) |
0

上一篇:BSD Mbuf

下一篇:BSD bind cpu

给主人留下些什么吧!~~