関数説明

以下に上記シグナル処理で重要な役割を担っている関数群について、処理の流れに沿って説明する。

  • sys_signal(sig, handler), do_sigaction(sig, action...)
    • シグナル種別sigのシグナルハンドラとしてhandlerで示される 関数を登録。登録先はプロセス固有のシグナルハンドラ テーブル(struct signal_struct)であり、それぞれのプロセステーブル (struct task_struct)からリンクされる。
    • do_sigaction関数はシグナルハンドラ実行に関する更に 細かい指定を行うことが可能である。
  • send_sig(sig, p)
    • pで示されるプロセスに、sigで示されるシグナルを送りつける。
    • シグナルハンドラが無視(SIG_IGN)指定の場合は、何も行わない。 ただし、SIGCHLDの場合は無視(SIG_IGN)指定の場合でも送り付ける。
    • シグナルがマスクされていない場合は、対象プロセスをシグナル 保留状態にする(task_structのsigpendigフラグをオン)。 シグナル送信対象のプロセス、シグナル受け付け可能 (TASK_INTERRUPTIBLE)状態で待ちに入っている場合は、 強制的に起床(wake_up_process関数)させる。
  • do_signal()
    • シグナルを送られたプロセスが呼び出すシグナル受信処理。 シグナルの種類により動作が異なる。
    • シグナル処理としてデフォルト(SIG_DFL)が指定されている場合は、 通常のシグナルではプロセスを終了(do_exit関数)せる。 シグナルの種類により、終了処理前にコアファイル生成 (バイナリファイルタイブ毎に用意されているcore_dump関数)を行う。

ただし、サスペンド系のシグナルの場合は、タスクをTASK_STOPPED 状態に遷移させる。

    • シグナル種別がSIGCHILDでかつ無視(SIG_IGN)指定の場合は、 ZONBIEとなった子プロセスの開放処理を行う(sys_wait関数)。
    • シグナル処理としてハンドラ起動が登録されている場合、 プロセスがシグナルハンドラを実行するための準備を行う。 (handle_signal関数)
  • handle_signal() .....(上記図を参照のこと)
    • プロセス空間にシグナルハンドラ実行用のスタックを用意し、 このスタックの初期化(setup_frame)を行う。登録されていればシグナル 実行専用領域をスタックとして利用するが、通常はプロセスの ユーザスタック上に確保される。
      • カーネルスタック上にあるプロセスの各種コンテキスト情報を シグナルハンドラ実行用のスタックにコピーする。 (再実行指定のシステムコール発行中にシグナルを 受けていた場合は、戻り番地をシステムコール命令 (int命令)のサイズ分巻き戻しておく)
      • カーネルスタック上にあるプロセスの各種コンテキストを捏造する。 戻り番地(eip)をユーザが定義したシグナルハンドラ、 ユーザスタック(esp)を今確保したシグナルハンドラに書き直す。 これにより、このプロセスがユーザモードに復帰したとき シグナルハンドラから実行を開始することになる。
      • ユーザ定義のシグナルハンドラの実行が終了したら、 自動的にsigreturnシステムコールが発行されるように シグナルハンドラ実行用のスタックを捏造する。 スタックの底に、sigreturnシステムコールを発行する テキストをコピーする(少々強引)。 シグナルハンドラ実行用のスタックの先頭に、 このテキストのアドレスを積んでおく。 これによりユーザ定義のシグナルハンドラからreturnすると 自動的にsigreturnシステムコールが置かれたテキストが 実行される。
    • プロセスのシグナルマスク状態を変更。一般的にシグナルハンドラ 実行中は同種のシグナルを受け付けないようにマスクを行う。 (シグナルハンドラ登録時の指定により異なる)
  • sys_sigreturn() .....(上記図を参照のこと)
    • ユーザのシグナルハンドラが終了するとsigreturnシステムコールが 自動的に呼び出される。
    • シグナルハンドラ中にあるコンテキストをカーネルスタック上の コンテキストにコピーして戻す。これにより、プロセスが Linuxカーネル(sigreturnシステムコール)から復帰すると、 シグナルを受ける直前の状態から再開することが可能となる。
    • シグナルハンドラから、スタック中にあるコンテキスト領域(シグナル 受信時のレジスタ群のコピー)を参照更新することも可能である。

(NIS)HirokazuTakahashi
2000年06月11日 (日) 22時29分57秒 JST
1