????3??sigaction()

????sigaction()???????????£?

sigaction(int signum?? const struct sigaction *act?? struct sigaction *oldact);

????sigaction()????????????do_sigaction()????????????彲??do_sigaction()?????????????£?

????3.1 do_sigaction()

int
do_sigaction(int sig?? const struct k_sigaction *act?? struct k_sigaction *oact)
{
 struct k_sigaction *k;

 if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig)))
  return -EINVAL;

 k = &currentt->sighand->action[sig-1];

 spin_lock_irq(&currentt->sighand->siglock);
 if (signal_pending(current)) {
  /*
   * If there might be a fatal signal pending on multiple
   * threads?? make sure we take it before changing the action.
   */
  spin_unlock_irq(&currentt->sighand->siglock);
  return -ERESTARTNOINTR;
 }

 if (oact)//???????k_sigaction???浽oact???У????????????????????и???
  *oact = *k;

 if (act) {
  /*
   * POSIX 3.3.1.3:
   *  "Setting a signal action to SIG_IGN for a signal that is
   *   pending shall cause the pending signal to be discarded??
   *   whether or not it is blocked."
   *
   *  "Setting a signal action to SIG_DFL for a signal that is
   *   pending and whose default action is to ignore the signal
   *   (for example?? SIGCHLD)?? shall cause the pending signal to
   *   be discarded?? whether or not it is blocked"
   */
  if (act->sa.sa_handler == SIG_IGN ||
      (act->sa.sa_handler == SIG_DFL &&
       sig_kernel_ignore(sig))) {
   /*
    * This is a fairly rare case?? so we only take the
    * tasklist_lock once we're sure we'll need it.
    * Now we must do this little unlock and relock
    * dance to maintain the lock hierarchy.
    */
   struct task_struct *t = current;
   spin_unlock_irq(&t->sighand->siglock);
   read_lock(&tasklist_lock);
   spin_lock_irq(&t->sighand->siglock);
   *k = *act; //???μ?k_sigaction????????????sighand->action??

   sigdelsetmask(&k->sa.sa_mask??
          sigmask(SIGKILL) | sigmask(SIGSTOP));
   rm_from_queue(sigmask(sig)?? &t->signal->shared_pending);
   do {
    rm_from_queue(sigmask(sig)?? &t->pending);
    recalc_sigpending_tsk(t);
    t = next_thread(t);
   } while (t != current);
   spin_unlock_irq(&current->sighand->siglock);
   read_unlock(&tasklist_lock);
   return 0;
  }

  *k = *act; //???μ?k_sigaction????????????sighand->action??
  sigdelsetmask(&k->sa.sa_mask??
         sigmask(SIGKILL) | sigmask(SIGSTOP));
 }

 spin_unlock_irq(&currentt->sighand->siglock);
 return 0;