看門狗在嵌入式 Linux 中的應用
By Toradex胡珊逢
1). 簡介
在嵌入式領域中 Watchdog 看門狗通常被作為用于應對系統或者應用意外崩潰的有效手段。其可以在程序執行出錯并無法恢復的情況下,自動重啟應用甚至復位整個系統,從而使系統脫離宕機狀態,恢復正常業務執行。這對于涉及到人身、財產安全的應用,顯得極為重要。本文將基于NXP iMX6 嵌入式平臺如何使用看門狗進行介紹,應對 Linux 系統或者應用程序意外崩潰。
本文所演示的iMX6平臺來自于Toradex Colibri iMX6 計算機模塊,iMX6芯片自帶看門狗功能,其硬件和早期的 iMX2 一致,所以看門狗驅動仍然沿用 imx2-wdt。看門狗只支持單用戶操作,即只能有一個實例來使用看門狗。因此在 Linux 系統中,用戶可以選擇由自己的應用直接使用看門狗,但只限于一個進程。看門狗只監控該應用,對于Linux 本身或者其他應用則無法在意外崩潰的情況下觸發看門狗復位。或者使用 systemd (183以后的版本)來操作硬件看門狗,同時為用 systemd 所管理的單元提供軟件邏輯看門狗。硬件看門狗主要應對 Linux 內核以及 systemd 自身的崩潰,軟件邏輯看門狗則可以用于用戶自己的應用,且不受數量限制。
2). 用戶應用操作
./ 首先在 U-Boot 中設置看門狗超時時間,這里設置為 60 秒。
------------------------
setenv defargs $defargs imx2-wdt.timeout=60
saveenv
------------------------
./ 編譯完成后運行測試程序。
------------------------
root@colibri-imx6:~# ./wdt-sample-app &
[1] 627
------------------------
./ 終結該測試程序進程。當進程被終結后,看門狗仍舊保持運行,但是無法定時喂狗。因此,在60s 超時后,看門狗會復位系統。
------------------------
root@colibri-imx6:~# kill 627
root@colibri-imx6:~# [ 45.964155] watchdog: watchdog0: watchdog did not stop!
[1]+ Terminated ./wdt-sample-app
------------------------
./ 當模塊由于看門狗復位時,可以從U-Boot 啟動的串口日志發現復位的原因。
------------------------
U-Boot 2016.11-2.8.5+g02735f4004 (Dec 28 2018 - 01:54:12 +0000)
CPU: Freescale i.MX6DL rev1.1 at 792 MHz
Reset cause: WDOG
I2C: ready
DRAM: 512 MiB
------------------------
3). Systemd 操作
a). 對于需要使用看門狗監控多個應用,可以使用 systemd 來操作。Systemd 提供硬件看門狗和軟件看門狗支持。硬件看門狗用于監控 Linux 內核以及 systemd 自身的運行,一旦出現內核崩潰的情況,看門狗超時將觸發系統復位。在 systemd 中使用硬件看門狗非常簡單,只需要配置 /etc/systemd/system.conf 中的RuntimeWatchdogSec= 參數,將其設置超時時間即可。在規定時間如果沒有喂狗,將觸發復位。systemd 通常會在所設置時間的一半為間隔進行喂狗。ShutdownWatchdogSec= 則可以設置關機超時時間,如果系統在該時間內沒有完成關機,也將系統復位。
./ 為了觸發內核崩潰的情況,我們需要開啟內核調試的 MAGIC_SYSRQ 功能,該選項在 Toradex 默認的 Linux BSP 中是關閉的。打開后重新編譯內核。
------------------------
CONFIG_MAGIC_SYSRQ=y
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
CONFIG_DEBUG_KERNEL=y
------------------------
./ 設置超時時間為60秒,RuntimeWatchdogSec=60。 啟動查看系統日志,顯示硬件看門狗超時時間被設置為1分鐘。
------------------------
root@colibri-imx6:/etc/systemd# dmesg|grep watchdog
[ 3.137012] systemd[1]: Hardware watchdog 'imx2+ watchdog', version 0
[ 3.147564] systemd[1]: Set hardware watchdog to 1min.
------------------------
./ 然后我們用下面命令觸發內核崩潰。
------------------------
echo c > /proc/sysrq-trigger
------------------------
./ 一分鐘以后,由于 systemd 沒有對進行喂狗操作,系統將復位后重新啟動。
b). 除了硬件看門狗外,sytemd 還提供軟件看門狗,每個 systemd service 都可以使用。service 需要讀取 WATCHDOG_USEC= 參數,確定看門狗超時時間,并在該時間范圍內使用 sd_notify("WATCHDOG=1") 喂狗,同樣喂狗的時間間隔為 WATCHDOG_USEC= 所設置的一半。
./ 用戶只要在對應的 systemd service 文件中設置 WatchdogSec= 參數即可,而 WATCHDOG_USEC= 將根據前面的參數自動被設置。在應用程序中以 WatchdogSec/2 的間隔調用 sd_notify 函數發送 "WATCHDOG=1"進行喂狗操作。例如
------------------------
// Systemd servier 文件(/etc/systemd/system/test.service),用于啟動用戶應用
[Unit]
Description=Watchdog Test service
[Service]
ExecStart=/home/root/wdt-sw-test
WatchdogSec=30s
Restart=on-failure
StartLimitInterval=5min
StartLimitBurst=4
StartLimitAction=reboot
[Install]
WantedBy=multi-user.target
------------------------
./ 用戶應用 wdt-sw-test.c,并定期執行喂狗操作(編譯的時候需要使用 -lsystemd 鏈接 systemd 庫文件)。
在應用初始化后需要通知 systemd 管理器本應用正常啟動,sd_notify (0, "READY=1");。然后根據 WATCHDOG_USEC 變量設置喂狗間隔。在應用中我們將模擬一次超時喂狗,從而引起應用重啟。
./ 下面是運行日志。起初應用程序 wdt-sw-test 由 systemd 加載啟動,PID=396,并以15s間隔喂狗(該時間源自WatchdogSec=30s)。當喂狗超時后,systemd 會發送信號 SIGABRT 終止該進程,并重啟該應用,新 PID=647。
./ 在 service 文件中,我們還配置了 StartLimitBurst 和 StartLimitInterval 以及 StartLimitAction 參數。這使得在 StartLimitInterval 時間內應用啟動次數超過 StartLimitBurst 后,將不被允許再次啟動,并觸發 StartLimitAction 的操作。具體描述請參考 systemd.unit。
4). 總結
看門狗對于關鍵應用,以及大多數的一般應用來講是一個很重要的功能,其能夠應對 Linux系統或者應用崩潰的情況,避免用戶設備處于失控的狀態。當整個系統只有一個嵌入式設備作為決策控制單元時,對于關鍵的安全應用,根據單一故障準則,我們還建議引入輔助控制單元,例如額外的 MCU 等做同步監測,或者使用保險絲、熱電偶等,當出現超限情況,能夠執行緊急操作,從而進一步提高設備的安全性。
*博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。