|
現: 2020-12-26 (土) 15:07:42 yuji  |
| + | * Watchdog Timer [#k34297ff] |
| + | 組み込み制御を行うシステムには,なんかあった時のために[[Watchdog Timer(ウォッチドッグタイマー)>https://ja.wikipedia.org/wiki/%E3%82%A6%E3%82%A9%E3%83%83%E3%83%81%E3%83%89%E3%83%83%E3%82%B0%E3%82%BF%E3%82%A4%E3%83%9E%E3%83%BC]]を必ず組み込む。 |
| | | |
| + | 通常はハードウェアで実装している(ソフトウェアで実装する場合は,そのソフトウェアの問題からは回避できないから)当たり前の機能ではあるが,Raspberry PiのSoCでもWatchdog Timerが利用できるようだ。 |
| + | |
| + | 何かあった時に自動で再起動するように出来るので有用ではあると思う。確認も兼ねてこの機能を使用するようにしてみた。 |
| + | |
| + | ** デバイスドライバーのロード [#b5548ee9] |
| + | /dev/watchdogデバイスを確認する。 |
| + | # ls -al /dev/watchdog* |
| + | 見つからない・・・ |
| + | |
| + | - ''Raspbian Jessieの場合'',~ |
| + | -- 設定ファイルの編集・作成~ |
| + | ''/etc/watchdog.conf''を編集する。 |
| + | max-load-1 = 24 <-- コメントを外す。 |
| + | watchdog-device = /dev/watchdog <-- コメントを外す |
| + | waatchdog-timeout = 10 <-- 追加 |
| + | -- カーネルモジュールのロード~ |
| + | ''/etc/modules''に以下を追加して,カーネルモジュールをロードするようにする。 |
| + | # echo "bcm2835_wdt" >> /etc/modules |
| + | その後,watchdog用のカーネルモジュールをロードします。 |
| + | # modprobe bcm2835_wdt |
| + | 正常にカーネルモジュールをロードできたか確認する。 |
| + | # lsmod | grep bcm2835_wdt |
| + | -- |
| + | bcm2835_wdt 4133 0 |
| + | -- |
| + | 0なので,まだこのカーネルモジュールを使用していないことになる。~ |
| + | -''Raspbian Stretchの場合'',~ |
| + | -- 設定ファイルの編集・作成~ |
| + | ''/etc/modprobe.d/bcm2835-wdt.conf''を作成する。~ |
| + | options bcm2835_wdt heartbeat=14 nowayout=0 |
| + | -- watchdogを有効にする~ |
| + | /boot/config.txtに,以下を追加する。~ |
| + | # activating the hardware watchdog |
| + | dtparam=watchdog=on |
| + | この後,リブートする。~ |
| + | これでDevice Treeでデバイスドライバーがロードされる。~ |
| + | |
| + | /dev/watchdog デバイスファイルが作成されているか確認する。~ |
| + | # ls -al /dev/watchdog* |
| + | crw------- 1 root root 10, 130 May 19 07:09 /dev/watchdog |
| + | crw------- 1 root root 253, 0 May 19 07:09 /dev/watchdog0 |
| + | 今度は,デバイスファイルが見つかった。 |
| + | |
| + | Watchdog Timerをバックグラウンドでカウントアップしていき,設定された時間に達するとシステムをリセットする。~ |
| + | |
| + | *** デバイスドライバーの確認 [#xdba0b67] |
| + | - Raspbian Jessieの場合~ |
| + | # lsmod | grep bcm2835_wdt |
| + | -- |
| + | bcm2835_wdt 4133 1 |
| + | 1となっているのでモジュールがロードされ,使用しているようだ。 |
| + | - Raspbian Stretchの場合~ |
| + | Kernel起動時にロードされるようだ。~ |
| + | # dmesg | grep bcm2835-wdt |
| + | [ 1.066065] bcm2835-wdt bcm2835-wdt: Broadcom BCM2835 watchdog timer |
| + | |
| + | ** watchdog resetデーモンの用意 [#e94b6874] |
| + | watchdog resetを行うプログラムを用意する。~ |
| + | これにより定期的にwatchdog timerをリセットしてカウンターを0にする。~ |
| + | |
| + | システムが正常な場合このプログラムも正常に動作し続けるため,Watchdogシステムによるリセットが行われないようになっている。~ |
| + | |
| + | 今回はバックグラウンドで動いているプログラムによりwatchdog timerをリセットしている。本来は重要なプログラムでwatchdog timerをリセットすべきだと思う。~ |
| + | - ''Raspbian Jessieの場合''~ |
| + | watchdog resetデーモンをインストールする。パッケージ管理ツールでインストールできる。~ |
| + | # apt-get install watchdog |
| + | -- watchdog.serviceファイルの編集~ |
| + | ''/lib/systemd/system/watchdog.service''ファイルを編集する。~ |
| + | [Install]の下に,WantedBy=multi-user.targetを追加する。~ |
| + | .... |
| + | [Install] |
| + | WantedBy=multi-user.target |
| + | -- 起動時にwatchdog resetデーモンが自動起動するように設定し,起動する。~ |
| + | # systemctl enable watchdog |
| + | # systemctl start watchdog |
| + | - ''Raspbian Stretchの場合''~ |
| + | systemdにより14秒以内の間隔でハートビートを行うように設定する。~ |
| + | 特にデーモンを自動起動させるための設定は必要はないようだ。systemdが起動すると機能が有効になるようになっているようだ。~ |
| + | -- 設定ファイルの編集~ |
| + | ''/etc/systemd/system.conf''ファイルを編集する。~ |
| + | #RuntimeWatchdogSec=0 |
| + | を, |
| + | RuntimeWatchdogSec=14 |
| + | に変更する。~ |
| + | |
| + | * Watchdog Timerの動作テスト [#x9f26a0c] |
| + | とりあえずWatchdog timerにより再起動(リセット)するかどうか確認してみる。~ |
| + | |
| + | これには,無理やりシステムを停止するようなコマンドを実行してみる。~ |
| + | Bashの入力プロンプトで,「:(){ :|:& };:」と入力する((フォークボムとかFork爆弾とか呼ばれている。DoS攻撃の一種で,新たなプロセスを生成するfork機能を使ったもの。Fork爆弾はワームやウイルスのようにコンピュータからコンピュータへ広がることはない。コンピュータ上で同時に実行可能なプログラム数あるいはプロセス数に制限があることを利用している。))と, |
| + | $ :(){ :|:& };: |
| + | なぜかシステムを停止することができちゃう :p |
| + | |
| + | '':''という関数(引数なし)を定義することを宣言している。~ |
| + | 続く''{ :|:& };''がその本体で,自分自身を2つ起動してパイプでつないで,バックグラウンドで実行することを意味する。バックグラウンドなので親プロセスをkillしても子プロセスは終了しない。~ |
| + | 最後の'':''が,その関数の実行開始を意味している。~ |
| + | |
| + | この文字列は,関数名を'':''としていることがわかりにくくしている。もっと判りやすい名前に置換すると次のようになる。~ |
| + | forkbomb(){ forkbomb|forkbomb & } ; forkbomb |
| + | |
| + | 同じ機能をCの場合は, |
| + | #include <unistd.h> |
| + | |
| + | int main() |
| + | { |
| + | while(1) |
| + | fork(); |
| + | return 0; |
| + | } |
| + | でプログラムできる。 |
| + | |
| + | Pythonだと, |
| + | import os |
| + | |
| + | while True: |
| + | os.fork() |
| + | になるのかな。 |