一、问题
在看nanosleep的时候,看到这个函数返回的错误码是-ERESTART_RESTARTBLOCK,所以就比较好奇的看了这个地方的代码,然后看到是在do_signal和handle_signal函数中判断了这些错误码的意义。然后就看一下它们具体的意义。
二、信号的发送
sys_kill(int pid, int sig)---》》》kill_something_info---》》》kill_pid_info---》》》group_send_sig_info----》》》__group_send_sig_info
/* Short-circuit ignored signals. */
if (sig_ignored(p, sig))
return ret;
if (LEGACY_QUEUE(&p->signal->shared_pending, sig))
/* This is a non-RT signal and we already have one queued. */
return ret;
这里的内核可忽略信号有
static int sig_ignored(struct task_struct *t, int sig)
{
void __user * handler;
/*
* Tracers always want to know about signals..
*/
if (t->ptrace & PT_PTRACED)
return 0;
/*
* Blocked signals are never ignored, since the
* signal handler may change by the time it is
* unblocked.
*/
if (sigismember(&t->blocked, sig))
return 0;
/* Is it explicitly or implicitly ignored? */
handler = t->sighand->action[sig-1].sa.sa_handler;
return handler == SIG_IGN ||
(handler == SIG_DFL && sig_kernel_ignore(sig));
}
也就是
#define sig_kernel_ignore(sig) \
(((sig) < SIGRTMIN) && T(sig, SIG_KERNEL_IGNORE_MASK))
这些信号如果没有安装信号处理函数,那么这个地方发送信号也不会将线程唤醒。
但是我们现在假设是其它的信号。
三、信号的执行
static void fastcall do_signal(struct pt_regs *regs)---》》》get_signal_to_deliver
signr = dequeue_signal(current, mask, info);
……
ka = ¤t->sighand->action[signr-1];
if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */
continue;
if (ka->sa.sa_handler != SIG_DFL) {
/* Run the handler. */
*return_ka = *ka;
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
break; /* will return non-zero "signr" value */
}
/*
* Now we are doing the default action for this signal.
*/
if (sig_kernel_ignore(signr)) /* Default is nothing. */ 走到这里,说明这个信号是SIG_DFL,否则将会在上面直接退出。
continue;
假设对于其它的不能忽略信号,例如SIGPIPE信号,此时就会执行到上面的SIG_IGN的时候进入continue,从而这个信号被消耗掉,从而执行到下面的返回,最终这个函数返回的信号值可能为零。
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
/* Reenable any watchpoints before delivering the
* signal to user space. The processor register will
* have been cleared if the watchpoint triggered
* inside the kernel.
*/
if (unlikely(current->thread.debugreg[7]))
set_debugreg(current->thread.debugreg[7], 7);
/* Whee! Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return;
}
/* Did we come from a system call? */
if (regs->orig_eax >= 0) { 只有返回值为零,才会执行下面的函数,说明信号被忽略了或者说是缺省处理。
/* Restart the system call - no handlers present */
switch (regs->eax) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
regs->eax = regs->orig_eax;
regs->eip -= 2;
break;
case -ERESTART_RESTARTBLOCK:
regs->eax = __NR_restart_syscall;
regs->eip -= 2;
break;
}
}
对于未忽略的信号,处理流程为
/* Are we from a system call? */
if (regs->orig_eax >= 0) {
/* If so, check system call restarting.. */
switch (regs->eax) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
regs->eax = -EINTR;
break;
case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->eax = -EINTR;
break;
}
/* fallthrough */
case -ERESTARTNOINTR:
regs->eax = regs->orig_eax;
regs->eip -= 2; 只有这种情况下一定会处理信号,其它的都没有保证。也就是说,只要安装了信号处理函数,那么很可能会都不会重新执行系统调用。
}
}
原文:https://www.cnblogs.com/tsecer/p/10485729.html