应用程序发送信号时,主要通过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;
}