WinCE/WEC のウォッチドッグタイマ機能.NET CF アプリケーションからデバッグメッセージ出力

WinCE/WEC のウォッチドッグタイマ機能(補足)

2012/03/27 koga

前回のエントリでは、WinCE/WEC のウォッチドッグタイマ機能について、ハードウェアタイマとソフトウェアタイマの二種類があることを述べました。そして、ハードウェアタイマとソフトウェアタイマでは、ソフトウェアタイマの方が、より柔軟であり、以下の点が異なると説明しました:

  1. ソフトウェアタイマは、複数の監視対象を設定できる(タイマを複数作成できる)
  2. ソフトウェアタイマは、タイマ満了時に発火させるアクションとして、デバイスをリセットする以外の動作を設定できる
  3. ソフトウェアタイマの場合は、カーネルではなく、監視対象のアプリケーションやスレッドが、タイマのリフレッシュ動作を行う

今回のエントリでは、上に示した、ハードウェアタイマとソフトウェアタイマの違いのうち、2. について補足します。ウォッチドッグタイマ機能において、ソフトウェアタイマとハードウェアタイマのどちらも、タイマの満了時にデバイスをリセットできますが、リセット動作の詳細は、異なるのです。

■ハードウェアタイマについての注意点
前回のエントリでは、ソフトウェアタイマがタイマ満了時に発火させることのできる三通りのアクションのうち、WDOG_RESET_DEVICE のことを、「OS をリブート(デバイスをリセット)する」動作だと説明しました。この「OS をリブート」というのが、ハードウェアタイマとは違う点です。ハードウェアのウォッチドッグタイマは、プロセッサを強制リセットします。強制リセットする際、OS がどのように動作しているのかは関知しません。

ここで、ハードウェアタイマの場合には、WinCE/WEC のカーネルが(より正確には、ウォッチドッグタイマ用のカーネルスレッドが)タイマのリフレッシュ動作を行います。従って、ハードウェアタイマが満了したということは、カーネルが動作を停止しているということですから、プロセッサを強制リセットするのが妥当です。通常は、その通りです。しかし、何らかの不具合で OS 全体がフリーズしているわけではないのに、カーネルが動作を停止する場合もあるのです。どんな場合でしょうか?

それは、カーネルデバッガを使っている時です。カーネルデバッガを使ってデバッグ動作している状態では、ブレークポイントにヒットすると、OS 全体の動作が停止します。OS 全体の動作が停止した状態であっても、ハードウェアタイマは動作し続けますから、ハードウェアタイマの満了時間が過ぎると、その時点で、ハードウェアのウォッチドッグタイマの働きにより、プロセッサが強制リセットされてしまうのです。ソフトウェアタイマの場合には、タイマの動作も停止していますから、そのようなことは、起きません。

カーネルデバッガを使ったデバッグ中に、予期せぬ強制リセットが起きしてしまわないよう、カーネルデバッガを使う時にはハードウェアタイマを動かさないか、または、タイマの満了時間をできるだけ長い値に設定して下さい。

■ソフトウェアタイマによるリセット動作
さて、ソフトウェアタイマのリセット動作は、「OS をリブート」する点がハードウェアタイマと違うと上で述べました。これについて、説明します。

まず、ハードウェアタイマのリセット動作では、プロセッサのリセット信号線を使って、ハードウェアによるリセットを行います。つまり、ハードウェアのウォッチドッグタイマが、プロセッサに対してリセット信号を出力する(プロセッサのリセット入力信号線に供給する電圧の論理値を、リセット用の値に変化させる)ことによって、プロセッサを強制リセットします。

一方、ソフトウェアタイマでは、ウォッチドッグタイマ用のカーネルスレッドが、OS のリブート処理を始動することによって、リセット動作を起こします。具体的には、IOCTL_HAL_REBOOT を引数として KernelIoctl() を呼び出します。興味のある方は、ソースコードをご覧になってみて下さい。ウォッチドッグタイマ用のカーネルスレッドのソースは、前回述べた通り、
 %_WINCEROOT%/PRIVATE/WINCEOS/COREOS/NK/KERNEL/watchdog.c
にあり、WatchDogTimerThrd() が、そのスレッドが実行する手続きです。WatchDogTimerThrd() を見ると、ソフトウェアタイマのどれか一つが満了すると、タイマの状態が WD_STATE_SIGNALED になり、その結果、そのタイマに設定されたアクションが実行されることが分かります。タイマに設定されたアクションの実行は、WDTakeDfltAction() を呼び出すことによって行われますが、WDTakeDfltAction() では、タイマに設定されたアクションが WDOG_RESET_DEVICE の場合、IOCTL_HAL_REBOOT を引数として KernelIoctl() を呼び出す実装になっています。

IOCTL_HAL_REBOOT を引数として KernelIoctl() を呼び出すことによって OS のリブート動作が起きる仕組みについては、2009/07/20 のエントリ(「アプリケーションからリブート(または電源 OFF)~その1(1/2)」)に書いています。もし興味があれば、お読みになってみて下さい。

2009/07/20 のエントリで書いたように、カーネルスレッドが、IOCTL_HAL_REBOOT を引数として KernelIoctl() を呼び出した場合には、レジストリやファイルシステムのフラッシュ動作が実行されたのち、OALIoCtlHalReboot() が呼び出されます。OALIoCtlHalReboot() は、カーネル移植レイヤ(OAL)で実装されており、プロセッサごとに異なるリセット動作を実行します。一般的には、ハードウェアのウォッチドッグタイマの発火時間を短い値にセットしたのち、無限ループを実行し、ハードウェアタイマによってプロセッサを強制リセットさせます。

■ハードウェアタイマについて、もう一度だけ注意
ここで重要なことは、ソフトウェアタイマによるリセット動作では、プロセッサをリセットする前に、レジストリやファイルシステムのフラッシュ動作を実行する、という点です。このことにより、ウォッチドッグタイマが発火してリセット動作が起きた際に、永続記憶域上のレジストリ内容やファイルシステムが、壊れてしまう危険性が抑えられるのです。ソフトウェアタイマが発火する原因になった監視対象のアプリケーションが、ファイル操作を行っていた場合には、ファイル内容が壊れてしまう可能性はあります(ファイルの書き込みを行っている途中でフリーズした場合など)。しかし、ディレクトリが壊れて読めなくなってしまったりするといった致命的なことは、起きないようにするというわけです。

この点も、ハードウェアタイマとは違う点です。通常動作中に OS 全体がフリーズしてしまった場合は、強制リセットが起きるのは仕方ありません。しかし、カーネルデバッガを使ったデバッグ中に、ハードウェアタイマが満了してしまい、予期せぬ強制リセットによってレジストリやファイルシステムが壊れてしまう、というようなことが起きないよう、ハードウェアタイマを使う場合には、ご注意ください。

Entry Filed under: OS の内部動作

Leave a Comment

Required

Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Categories

Links

Posts by Authors

Recent Posts

Calendar

2012年3月
« 2月   4月 »
 123
45678910
11121314151617
18192021222324
25262728293031

Posts by Month

Posts by Category

Meta