このページを編集する際は、編集に関する方針に従ってください。

概要

  • linux2.6/kernel/signal.cにて定義
  • 引数で渡されたシグナル番号に対応するシグナルハンドラを実行する
    • 実行に成功した場合は0を、失敗した場合はエラーコードを返す

引数

実装

int do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) {

	struct k_sigaction *k;
	if (sig < 1 || sig > _NSIG || (act && sig_kernel_only(sig)))
		return -EINVAL;
  • シグナルsigが強制終了(SIGKILL)もしくは実行停止(SIGSTOP)を意味する場合は1を返す
	k = &current->sighand->action[sig-1];
	spin_lock_irq(&current->sighand->siglock);
  • ローカル割り込みを禁止し、プリエンプションを無効化し、スピンロックcurrent->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(&current->sighand->siglock);
  • スピンロックcurrent->sighand->siglockを開放して、外部割込みを有効する。プリエンプティブを有効にして可能であればプリエンプティブを実行する
		return -ERESTARTNOINTR;
	}
	if (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))) {
  • シグナルを無視することを意味する
  • デフォルトのシグナルハンドラ実行を意味する
  • シグナル番号sigがリアルタイムプロセスではなく、かつ既にマスクされていない場合に1を返す
			/*
			 * 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);
  • スピンロックt->sighand->siglockを開放して、外部割込みを有効する。プリエンプティブを有効にして可能であればプリエンプティブを実行する
			read_lock(&tasklist_lock);
  • プリエンプティブを不可にし、読み込み用ロックtasklist_lockの取得を試みる
    • ロックの取得に失敗した場合は待ち状態に入る
    • 詳細はread_lock()/linux2.6を参照
			spin_lock_irq(&t->sighand->siglock);
  • ローカル割り込みを禁止し、プリエンプションを無効化し、スピンロックt->sighand->siglockの取得を試みる
			*k = *act;
			sigdelsetmask(&k->sa.sa_mask,
				      sigmask(SIGKILL) | sigmask(SIGSTOP));
  • シグナル番号SIGKILL,SIGSTOPからシグナルのマスクを作る
  • 現在マスクしているシグナルを表す構造体から、引数で渡されたマスクに該当するビットをクリアする
			rm_from_queue(sigmask(sig), &t->signal->shared_pending);
  • シグナル番号sigからシグナルのマスクを作る
  • 引数で渡されたシグナルが属するシグナルキューからマスクに該当するシグナルを削除する
			do {
				rm_from_queue(sigmask(sig), &t->pending);
  • シグナル番号sigからシグナルのマスクを作る
  • 引数で渡されたシグナルが属するシグナルキューからマスクに該当するシグナルを削除する
				recalc_sigpending_tsk(t);
  • タスクpに、ブロックしていない保留中のシグナルがあるか確認する
				t = next_thread(t);
  • タスクtのスレッドグループの中から次のタスクを見つけて返す
			} while (t != current);
			spin_unlock_irq(&current->sighand->siglock);
  • スピンロックcurrent->sighand->siglockを開放して、外部割込みを有効する。プリエンプティブを有効にして可能であればプリエンプティブを実行する
			read_unlock(&tasklist_lock);
  • 読み込みロックtasklist_lockを解放した後、プリエンプション機能を有効にし可能であれば自ら積極的にプリエンプション(実行権の移譲を行うこと)する
			return 0;
		}
		*k = *act;
		sigdelsetmask(&k->sa.sa_mask,
			      sigmask(SIGKILL) | sigmask(SIGSTOP));
  • シグナル番号SIGKILL,SIGSTOPからシグナルのマスクを作る
  • 現在マスクしているシグナルを表す構造体から、引数で渡されたマスクに該当するビットをクリアする
	}
	spin_unlock_irq(&current->sighand->siglock);
  • スピンロックcurrent->sighand->siglockを開放して、外部割込みを有効する。プリエンプティブを有効にして可能であればプリエンプティブを実行する
	return 0;

}

呼出元

履歴

  • 作者:ひら
  • 日付:2007/2/6
  • 対象:2.6.10
    更新日更新者更新内容

コメント/タグ?


  • 1 -- 2014-07-28 (月) 14:38:36
    • 1' -- 2014-07-28 (月) 14:38:35
  • 1 -- 2014-07-28 (月) 14:38:33
  • 1 -- 2014-07-28 (月) 14:38:31
  • 1 -- 2014-07-28 (月) 14:38:28
  • 1 -- 2014-07-28 (月) 14:38:11

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2014-07-28 (月) 14:38:37 (1361d)