産業用ラズパイは外部ウォッチドッグ(WD)で堅牢性がアップする仕組み

はじめに

システムが障害を起こしてフリーズ(以下、ハングアップ)した場合、再起動といった作業が必要になります。
人が操作できないタイミングや、人が容易にアクセスできないシステムの設置場所、もしかしたら人手不足により対応できる人材が見つからないなど、物理的にリセットすることが困難な場合があります。
システムが止まっているわけですから、遠隔での操作も困難になります。

そこでウォッチドッグ(以下、WD)という仕組みがあります。

WDが担っていることは監視というシンプルな役割です。
定期的にチェックして、システムが異常をきたしたら、システムにリセットがかけられる役割が一般的です。

今回は産業用ラズパイ「PL-R4」でWDを設定してみました。
独自に配置しているWDと、マイクロプロセッサチップ内部に組み込まれているWDとの違いをなるべく分かりやすくまとめてみました。

外部にWDが配置してあれば、確実にリセットがかけられるため、産業用途では必要になる機能の1つです。

ウォッチドッグは定期的な監視機能

WDはWDT(ウォッチドッグタイマー)とも言われます。「ウォッチドッグ」の言葉自体は英語で番犬であり、犬でなければ監視人といった意味になります。

つまり、定期的に特定の場所を監視する機能(機構)ということです。番犬のように見張っているわけですね。

何を見張っているのかというと、システムが正常に動いているかどうかです。

WDは外部にIC部品として設置するパターンと、マイクロプロセッサチップ内部に組み込まれているパターンがあります。
一般的なPCは内部に組み込まれている製品が多くなりました。古くはマイコン時代(PC-98、88)、本体にあからさまにリセットボタンが付いており、異常時には人がリセットボタンを押して復旧させていました。

WDは常に異常を監視し、異常時は自動的にリセットがかかる仕組みです。

外部WDの利点

市販のRaspberry Pi は、マイクロプロセッサチップ内部にWDが組み込まれています。設定ファイルで制御できるやり方です。

一方、産業用ラズパイ「PL-R4」のWDは、外部WDとして実装されています。WDの機能の有効/無効をディップスイッチで制御できるようにも設計されています。

外部に配置されている最大のメリットは、通電さえしていればWDは確実に動作する点です。

内部WDでは、マイクロプロセッサチップ内部あるため、WDタイマー自体が止まってしまうと、それで動いているWDのカウントも止まってしまい機能しないパターンが考えらるからです。
これではシステムのリセットがかけられず、デバイスそのものに人間がアクセスしないと解決できなくなります。

デバイスの設置場所によっては、容易に手が届かない場所もある産業用途では、この事態を避ける意味でも外部WDは必要になります。

市販のRaspberry PiでWDを外部に実装するには、拡張HATなどで実現できますが、本体基板に設置するには、基板のサイズ問題やコストアップの点から難しいですね。

産業用ラズパイだからこそ、WDも外部に設置させてあり、ほぼハングアップしない環境を確保しています。

ウォッチドッグの役割と働き

実際にWDは何をしているのかというとやや難しいのですが、カウンター(時間)という形で一定間隔を測っているだけといえます。

とても抽象的に例えると、ドアをノックしたら1秒後に返事があるとします。これを定期的にノックしていて、あるとき2秒経っても3秒経っても返事がなく、5秒を経過したらこれを異常事態と認識しドアを開ける(再起動をかける)ように指示すると想像してください。

WDはWDT(ウォッチドッグタイマー)というように、常に一定間隔のカウント(タイマー)と、そのカウントをリセットする処理を繰り返しさせます。

これは人で言うなら安否確認と同じですね。
「元気ですか?」と一定間隔で訪問しているわけです。
いつもなら応答があるのに、今日は何分待っても出て来ないと心配ですよね。

WDは、いつもと違う状態、つまりそれは異常事態と判断するための役割と働きです。

産業用ラズパイ「PL-R4」にある外部WDのタイマーは、次のようになっています。

①はシステム起動時にWDが待機する時間です。「60 180」とあるように多少の振れ幅があり、1分〜3分となります。
実際には概ね2分(120秒)でWDが動作し始めます。

②の部分にある「1 3」とあるのは、リセットがかかる秒数です。こちらも多少の振れ幅があり、1秒〜3秒となっています。
実際には概ね2秒でシステムリセットがかかります。

例外を避けて確実な動作にするため、それぞれ60秒未満、1秒未満を前提にするプログラミングになるでしょう。

システムのリセットになる時間より短い時間でWDカウンターをリセットし続けることで、通常動作を継続させる役割を担っています。

もしも何らかの異常で、WDのカウントがリセットされない場合は、システムがリセット(再起動)するわけです。

WDの設定(PL-R4の場合)

以下、市販されているRaspberry Pi とは設定方法が異なります。「PL-R4」での設定です。

Raspberry Pi OSにプリインストールされているWDは、マイクロプロセッサチップ内にあるソフトウェアウォッチドッグです。今回は直接関係はありません。
「PL-R4」の場合は次が必要です。

  • ディップスイッチの切替
  • config.txtの編集
  • 独自プログラムの実行

ディップスイッチの切替

基板にある2箇所にあるディップスイッチの1番目を、それぞれON側にすることでWD機能を有効化させます。
具体的な場所は写真の通りです。

スイッチの切替だけではWDは有効になりません。
続いてconfig.txtを修正し、独自のPythonプログラムを自動実行させる設定をしていきます。

config.txtの編集

config.txtの[all]セクションにあるWD/CSIがコメントアウトになっていたら外して有効にします。カメラモジュールのCSIと排他利用です。

sudo nano /boot/config.txt

変更するは次の箇所です。
コメントアウトしておらず有効になっている箇所を確認してください。

[all]

dtparam=i2c0_baudrate=400000
dtoverlay=i2c0,pins_0_1

#WD/CSI select
dtparam=i2c1_baudrate=400000
dtoverlay=i2c1,pins_44_45

#dtoverlay=imx708

概ねカメラモジュールで使ったCSIポート利用とは逆になります。

プログラム例

最後に必要なのは、定期的に外部WDをリセットさせるプログラムです。

冒頭に述べたように、一定のタイマーカウントかどうかを測る目的です。
このテストプログラムでは、GPIOの44、45番を使い定期的にWDをリセットさせています。

Pythonプログラム例:

import RPi.GPIO as GPIO
import time

WDEPIN = 44
WDRPIN = 45

GPIO.setwarnings(False)

GPIO.setmode( GPIO.BCM )
GPIO.setup( WDEPIN, GPIO.OUT )
GPIO.setup( WDRPIN, GPIO.OUT )


while 1:
        GPIO.output( WDEPIN, False )
        GPIO.output( WDRPIN, True )
        time.sleep( 1.0 )
        GPIO.output( WDRPIN, False )
        time.sleep( 1.0 )

実際には独自アプリケーションなどに組み込むことも必要になります。

テストの目的として、上記wdrst.pyファイルを起動時に実行させます。/etc/rc.localへ記述します。
逆にWDを使わない場合は、rc.localの記述はコメントアウトまたは削除して自動起動させないようにします。

rc.localへの追記:

#WD
python /home/pi/wdrst.py

exit 0

ここでは省きますが、rc.localはRaspberry Pi で自動実行させるプログラムを記述する手段の1つです。
rc.localへ追記するには、最初からあるexit0の前に記述していく形になります。

これで再起動後はWD機能が有効になっている状態です。
早速、動作を確認してみます。

WDの動作確認

再起動後、WDが機能するのか確認する方法として、実際にシステムをハングアップさせることで、自動的に再起動するのかで確認します。

人為的にハングアップさせるため、フォークボム(forkbomb)の実行やカーネルパニック(kernel Panic)を引き起こすコマンドを利用します。

フォークボム

フォームボムは、プロセスを次々と複製させることで総プロセス数が膨大になり、他のプロセスが入り込む余地を与えません。
実行した瞬間からシステム全体の動作が遅くなるのが分かります。
SSHで接続していると、SSHすらすぐに動かなくなります。

フォークボムのshellコマンド:

:(){ :|:& };:

実行後は次のようにターミナルに表示されます。
今回の環境では10~15秒ほど経過した後に再起動しました。成功です。

-bash: fork: retry: リソースが一時的に利用できません
-bash: fork: メモリを確保できません
-bash: fork: retry: リソースが一時的に利用できません
(続く)

リソースの枯渇といったことから他のプロセスは動作せずハングアップし、WDで定期的にチェックしていた一定カウントとを超えた結果として、システムが再起動になったというわけです。

カーネルパニック

カーネルパニックも何かしらの異常でシステムが止まった状態を再現できます。

Windowsユーザーには馴染みがないカーネルパニックは、内部的に致命的なエラーに陥ると起きます。
私もRaspberry Pi 3や4で2〜3度遭遇しました。

ソフトウェア側やハードウェア側のどちらが原因でも起きる現象ですが、Raspberry Pi ではmicroSDカードの破損で遭遇した経験があります。書き換えのし過ぎで起こり得ることです。何回というわけではなく、運が悪く3~4回でも経験しています。

以下コマンドは、root権限でなければ実行できませんので、sudo suで一時的にスーパーユーザーになり実行します。

カーネルパニックを起こすコマンド:

sudo su
echo c > /proc/sysrq-trigger

どちらでも設定した秒数程度で再起動することが確認できました。

WDが機能していない場合は、ハングアップしたままですから、人が物理的に電源を抜くといった形しか再起動ができません。
それに不具合が発生した瞬間が分からなければ、復旧の対処が遅れてしまい、しばらくシステムが稼働していないことになります。

システムを再起動させることで最低限の復旧対応ができます。

運用する環境に合ったデバイス選び

WDは、システムが正常に動作しているかの確認を、まさに番犬のように監視しています。

今回のWDも含め、大抵のことは市販のRaspberry Piでも試すことが可能です。
但し、産業用途でRaspberry Piを使う場合、より堅牢なシステムを要求されるでしょう。
設置場所によっては高温であったり、人が容易にアクセスできない場所であったり、設置する環境は様々だからです。

WDの動作検証の中で感じたのは、突発的なトラブルを回避するシステム環境を求めるなら、外部に実装されているWDは確実だなという印象でした。
市販のRaspberry Piと異なり、「PL-R4」が産業用途に特化している理由の1つとして理解することができました。

今回とは手法が異なりますが、市販のRaspberry Pi でも内部で構成されているWDが使えます。
内部WDでは、そもそもマイクロプロセッサチップが止まるとWDも止まってしまうため、再起動できない事象も出てきます。
試していると、やや確実性に欠けることに気が付けるかもしれません。

やはり外部に配置した外部WDは信用できる仕組みです。ハングアップ知らずのシステムは産業用ラズパイの選択が確実です。


記事寄稿:ラズパイダ

非エンジニアでも楽しく扱えるRaspberry Pi 情報サイト raspida.com を運営。ラズベリーパイに長年触れた経験をもとに、ラズベリーパイを知る人にも、これから始めたいと興味を持つ人にも参考になる情報・トピックを数多く発信。PiLinkのサイトへは産業用ラズベリーパイについて技術ブログ記事を寄稿。