Linux Kernel(2.6)の実装に関するメモ書き

プロセスのBlockとWakeup


Rev.10を表示中。最新版はこちら


プロセスの止め方

プロセスをブロックさせるには、WaitQueueを使ってブロックすれば、まとめてWakeupできる。

WaitQueueを使わない場合

1. currentをどこかに保存
2. set_current_state(TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE)
3. schedule() - プロセス切替え(ブロック)

wake_up_process()で1.で保存しておいたcurrentを指定すれば起床できる。

WaitQueueを使う場合

WaitQueueのエントリにはwakeup時のコールバックルーチンを指定しておく。本ルーチンを指定すれば、wakeup時に何か追加の処理を行える。通常はデフォルトでいいはず。

その1

1. DECLARE_WAITQUEUE()でWaitQueue用のエントリを作成
wakeup時のコールバックルーチンは
.func = default_wake_function が設定される。
2. set_current_state(TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE)
3. add_wait_queue() - WaitQueueに追加
4. schedule() - プロセス切替え(ブロック)
5. remove_wait_queue() - Wakeupされたら、WaitQueueから削除
6. set_current_state(TASK_RUNNING) - Running状態にする

その2

1. DEFINE_WAIT()でWaitQueue用のエントリを作成
wakeup時のコールバックルーチンは
.func = autoremove_wake_functionが設定される。
2. prepare_to_wait()
指定WaitQueueにエントリを追加
set_current_state()で状態を変更
(通常はTASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE)
3. schedule() - プロセス切替え(ブロック)
4. finish_wait() - Wakeupされた時の後処理
__set_current_state(TASK_RUNNING)でプロセスをRunning状態にしている。

wakeup時のコールバックルーチンでWaitQueueからの削除は行われているのでここでは不要



各処理部でその1のような方法で止めたり、その2の方法で止めたりまちまち。その2の方が、Wakup後にWaitQueueからエントリの削除を行なう必要がないので多少楽。

プロセスのRunQueueからの削除はschedule()で行われている。

止めたプロセスの起こし方

WaitQueueを使わずにtask_structのアドレスを保存しておいて止めた場合は、wake_up_process()でtask_structを指定すればよい。

WaitQueueを使用した場合は、wake_up()でWaitQueueを指定すればよい。wake_up()には派生ルーチンがあるが、どれもマクロで__wake_up()を使用している(include/linux/wait.h)。

Wakeupの流れ


wake_up(&WaitQueue) - 指定WaitQueueの全プロセスをWakeup
__wake_up()
__wake_up_common()
WaitQueueに連なっている各エントリのwakeup用
コールバック(xxx->func())を実行してプロセスをwakeup

DECLARE_WAITQUEUE()で作られたエントリならば
.func = default_wake_function
try_to_wake_up() - プロセスをRUNNING状態へ
<-- WaitQueueからは外されないので
プロセス再開後、自前で外す必要がある

DEFINE_WAIT()で作られたエントリならば
.func = autoremove_wake_function
default_wake_function() - 上述のルーチン
WaitQueueから外す



[関連ページ]
WaitQueue


最終更新 2006/06/26 00:25:39 - kztomita
(2006/06/24 19:46:51 作成)


リンク
最近更新したページ
検索