进程
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
阅读(1131) | 评论(0) | 转发(0) |