应用程序发送信号时,主要通过kill进行。注意:不要被“kill”迷惑,它并不是发送SIGKILL信号专用函数。这个函数主要通过系统调用sys_kill()进入内核,它接收两个参数:
第一个参数为目标进程id,kill()可以向进程(或进程组),线程(轻权线程)发送信号,因此pid有以下几种情况:
● pid>0:目标进程(可能是轻权进程)由pid指定。
● pid=0:信号被发送到当前进程组中的每一个进程。
● pid=-1:信号被发送到任何一个进程,init进程(PID=1)和以及当前进程无法发送信号的进程除外。
● pid<-1:信号被发送到目标进程组,其id由参数中的pid的绝对值指定。
第二个参数为需要发送的信号。
由于sys_kill处理的情况比较多,分析起来比较复杂,我们从太累了入手,这个函数把信号发送到由参数指定pid指定的线程(轻权进程)中。tkill的内核入口是sys_tkill(kernel/signal.c),其定义如下:
/* * Send a signal to only one task, even if it's a CLONE_THREAD task. */ asmlinkage long sys_tkill(int pid, int sig) { struct siginfo info; int error; struct task_struct *p;
/* This is only valid for single tasks */ if (pid <= 0)//对参数pid进行检查 return -EINVAL;
info.si_signo = sig; //根据参数初始化一个siginfo结构 info.si_errno = 0; info.si_code = SI_TKILL; info.si_pid = current->tgid; info.si_uid = current->uid;
read_lock(&tasklist_lock); p = find_task_by_pid(pid);//获取由pid指定的线程的task_struct结构 error = -ESRCH; if (p) { error = check_kill_permission(sig, &info, p);//权限检查 /* * The null signal is a permissions and process existence * probe. No signal is actually delivered. */ if (!error && sig && p->sighand) { spin_lock_irq(&p->sighand->siglock); handle_stop_signal(sig, p); //对某些特殊信号进程处理,例如当收到SIGSTOP时,需要把信号队列中的SIGCONT全部删除 error = specific_send_sig_info(sig, &info, p);//把信号加入到信号队列 spin_unlock_irq(&p->sighand->siglock); } } read_unlock(&tasklist_lock); return error; } |