Linuxカーネル上で動作するプロセスの状態は、大きく分けて2つある。1つは実行可能状態で、もう1つは待機状態(休止状態)だ。ここでは待機状態のプロセスについて詳しく解説していく。
Linuxカーネル上で動作するプロセスの状態は、大きく分けて2つあります。1つは実行可能状態で、もう1つは待機状態(休止状態)です。実行可能状態のプロセスはスケジューリングの対象となり、プロセススケジューラは順番に実行権を与えていきます。待機状態のプロセスは、何らかの事象を待ち合わせている状態であり、ある条件が整うまでそれ以上の処理を継続できません。このようなプロセスは、スケジューリングの対象にはなりません。例えば、ファイルのread処理を行っているプロセスは、ディスクへの入出力要求後、その入出力が完了するまで動作できません(図11)。実際、Linuxカーネル上で動作しているプロセスの大部分は、この待機状態にあります。
待機状態のプロセスには2種類あります。1つはシグナルを受け付ける待機状態で、もう1つはシグナルを受け付けない待機状態です。前者はソケットや端末などでの事象発生を待ち合わせるときに利用します。目的の事象が発生するか、またはシグナルを受け取ると、待機状態は解除され、実行待ち状態に遷移します。後者はシグナルを受けても、シグナルを保留状態にしたまま待機状態を続けます※。
Linuxカーネルはこれらの状態を区別できるように、task_struct構造体のstateメンバーに表1の状態を表す値を設定します。プロセスの状態遷移は図12のようになります。
値 | 意味 |
---|---|
TASK_RUNNING | 実行可能状態(実行状態、実行待ち状態) |
TASK_INTERRUPTIBLE | 待機状態。シグナルによる待機状態解除可能 |
TASK_UNINTERRUPTIBLE | 待機状態。シグナルによる待機状態解除不可 |
表1 プロセスの状態 |
待機の対象となる可能性のあるカーネルオブジェクト(ファイルや、実ページ、端末など)は、それぞれWAITキュー(wait_queue_head_t型のリストヘッド)を用意しています。待機状態に遷移したプロセスは、ある事象の待ち合わせ用に用意されているWAITキューに登録されます。Linuxカーネル内には、さまざまなWAITキューが存在します。例えば、ある端末の入力待ちのWAITキュー、ページキャッシュ上のページへの入出力完了を待ち合わせるためのWAITキュー、子プロセスの終了を待ち合わせるためのWAITキューなどがあります。
待機状態のプロセスは、図13のような形式でWAITキューに登録されます。WAITキューに直接task_struct構造体を登録することはせずに、wait_queue_t型のデータ構造を介して間接的に登録します。
実行中プロセスを待機状態に遷移させる関数は、実行中プロセスを待機状態にするsleep_on( )関数(リスト5)と、実行中プロセスをシグナル受信可能な待機状態にするinterruptible_sleep_on( )です。これらの関数は、プロセス状態をそれぞれTASK_UNINTERRUPTIBLE、TASK_INTERRUPTIBLEに変更し(52)、スタック上に確保したwait構造体(51)を使って、目的の事象を待ち合わせるためのWAITキューに登録します(53)。その後、プロセススケジューラを呼び出し、実行権を放棄します(54)。
void sleep_on(wait_queue_head_t *q) { unsigned long flags; wait_queue_t wait; init_waitqueue_entry(&wait, current); ← 51 current->state = TASK_UNINTERRUPTIBLE; ← 52 spin_lock_irqsave(&q->lock,flags); __add_wait_queue(q, &wait); ← 53 spin_unlock(&q->lock); schedule(); ← 54 spin_lock_irq(&q->lock); __remove_wait_queue(q, &wait); ← 55 spin_unlock_irqrestore(&q->lock, flags); }
待機状態を続けます: シグナルについては、別の回に詳しく説明する。
Copyright(c)2010 SOFTBANK Creative Inc. All rights reserved.