staticint send_signal(int sig, struct siginfo *info, struct task_struct *t, int group) { struct sigpending *pending; struct sigqueue *q; trace_sched_signal_send(sig, t); assert_spin_locked(&t->sighand->siglock); /*prepare_signal函数会调用sig_ignored检查信号是否被标记会堵塞 如果被标记为堵塞,就不处理了*/ if (!prepare_signal(sig, t)) return0; pending = group ? &t->signal->shared_pending : &t->pending; /* * Short-circuit ignored signals and support queuing * exactly one non-rt signal, so that we can get more * detailed information about the cause of the signal. */ if (legacy_queue(pending, sig)) return0; /* * fast-pathed signals for kernel-internal things like SIGSTOP * or SIGKILL. */ if (info == SEND_SIG_FORCED) goto out_set; /* Real-time signals must be queued if sent by sigqueue, or some other real-time mechanism. It is implementation defined whether kill() does so. We attempt to do so, on the principle of least surprise, but since kill is not allowed to fail with EAGAIN when low on memory we just make sure at least one signal gets delivered and don't pass on the info struct. */ /*分配一个sigqueue 结构图*/ q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN && (is_si_special(info) || info->si_code >= 0))); if (q) { /*将sigqueue结构体挂接到task_struct pending队列上面*/ list_add_tail(&q->list, &pending->list); switch ((unsignedlong) info) { case (unsignedlong) SEND_SIG_NOINFO: q->info.si_signo = sig; q->info.si_errno = 0; q->info.si_code = SI_USER; q->info.si_pid = task_tgid_nr_ns(current, task_active_pid_ns(t)); q->info.si_uid = current_uid(); break; case (unsignedlong) SEND_SIG_PRIV: q->info.si_signo = sig; q->info.si_errno = 0; q->info.si_code = SI_KERNEL; q->info.si_pid = 0; q->info.si_uid = 0; break; default: copy_siginfo(&q->info, info); break; } } elseif (!is_si_special(info)) { if (sig >= SIGRTMIN && info->si_code != SI_USER) /* * Queue overflow, abort. We may abort if the signal was rt * and sent by user using something other than kill(). */ return -EAGAIN; } out_set: signalfd_notify(t, sig); sigaddset(&pending->signal, sig); /*complete_signal函数唤醒休眠的进程*/ complete_signal(sig, t, group); return0; }
void signal_wake_up(struct task_struct *t, int resume) { unsignedint mask; /*设置进程为 sigpending状态*/ set_tsk_thread_flag(t, TIF_SIGPENDING); /* * For SIGKILL, we want to wake it up in the stopped/traced/killable * case. We don't check t->state here because there is a race with it * executing another processor and just now entering stopped state. * By using wake_up_state, we ensure the process will wake up and * handle its death signal. */ mask = TASK_INTERRUPTIBLE; if (resume) mask |= TASK_WAKEKILL; /*唤醒状态为 TASK_INTERRUPTIBLE的进程,这里特别要主要的是 TASK_UNINTERRUPTIBLE的进程不会被唤醒*/ if (!wake_up_state(t, mask)) kick_process(t); }