Linux 看門狗驅動程式 API

上次稽核:2007/10/05

版權所有 2002 Christer Weingel <wingel@nano-system.com>

本文件的部分內容逐字複製自 sbc60xxwdt 驅動程式,該驅動程式 (c) 版權所有 2000 Jakob Oestergaard <jakob@ostenfeld.dk>

本文件描述了 Linux 2.4.18 核心的狀態。

介紹

看門狗定時器 (WDT) 是一種硬體電路,在發生軟體故障時可以重置計算機系統。您可能已經知道了這一點。

通常,使用者空間守護程式會透過 /dev/watchdog 特殊裝置檔案,定期通知核心看門狗驅動程式使用者空間仍在執行。當發生此類通知時,驅動程式通常會告訴硬體看門狗一切正常,並且看門狗應該再等一小段時間才能重置系統。如果使用者空間發生故障(RAM 錯誤、核心錯誤等),通知就會停止,硬體看門狗會在超時發生後重置系統(導致重啟)。

Linux 看門狗 API 是一種相當臨時性的構造,不同的驅動程式實現了其中不同且有時不相容的部分。本文件旨在記錄現有用法,並允許未來的驅動程式編寫者將其用作參考。

最簡單的 API

所有驅動程式都支援基本操作模式,即看門狗在 /dev/watchdog 開啟後立即啟用,並且除非在特定時間內(此時間稱為超時或裕度)對看門狗進行“餵狗”,否則系統將重啟。對看門狗進行“餵狗”的最簡單方法是向裝置寫入一些資料。因此,一個非常簡單的看門狗守護程式將如下所示:請參閱 samples/watchdog/watchdog-simple.c 原始檔

一個更高階的驅動程式可以在執行寫入呼叫以“餵狗”看門狗之前,例如檢查 HTTP 伺服器是否仍在響應。

當裝置關閉時,看門狗將被停用,除非支援“魔術關閉”功能(見下文)。這並不總是一個好主意,因為如果看門狗守護程式中存在錯誤並且它崩潰了,系統將不會重啟。因此,一些驅動程式支援配置選項“關閉時停用看門狗關機”,CONFIG_WATCHDOG_NOWAYOUT。如果在編譯核心時將其設定為 Y,則一旦看門狗啟動,就無法停用它。因此,如果看門狗守護程式崩潰,系統將在超時後重啟。看門狗裝置通常還支援 nowayout 模組引數,以便可以在執行時控制此選項。

魔術關閉功能

如果驅動程式支援“魔術關閉”,則除非在關閉檔案之前向 /dev/watchdog 傳送了特定的魔術字元“V”,否則驅動程式不會停用看門狗。如果使用者空間守護程式在沒有傳送此特殊字元的情況下關閉檔案,驅動程式將假定守護程式(以及通常的使用者空間)已死亡,並將停止“餵狗”看門狗而不會先停用它。如果看門狗未在足夠的時間內重新開啟,這將導致重啟。

ioctl API

所有符合規範的驅動程式也支援 ioctl API。

使用 ioctl “餵狗”看門狗

所有具有 ioctl 介面的驅動程式都至少支援一個 ioctl,即 KEEPALIVE。此 ioctl 的作用與寫入看門狗裝置完全相同,因此上述程式中的主迴圈可以替換為

while (1) {
        ioctl(fd, WDIOC_KEEPALIVE, 0);
        sleep(10);
}

ioctl 的引數被忽略。

設定和獲取超時時間

對於某些驅動程式,可以使用 SETTIMEOUT ioctl 動態修改看門狗超時時間,這些驅動程式的選項欄位中設定了 WDIOF_SETTIMEOUT 標誌。引數是一個整數,表示以秒為單位的超時時間。驅動程式在同一變數中返回實際使用的超時時間,並且此超時時間可能由於硬體限制而與請求的不同

int timeout = 45;
ioctl(fd, WDIOC_SETTIMEOUT, &timeout);
printf("The timeout was set to %d seconds\n", timeout);

如果裝置的超時粒度為分鐘,此示例實際上可能會列印“超時設定為 60 秒”。

從 Linux 2.4.18 核心開始,可以使用 GETTIMEOUT ioctl 查詢當前超時時間

ioctl(fd, WDIOC_GETTIMEOUT, &timeout);
printf("The timeout was is %d seconds\n", timeout);

預超時

一些看門狗定時器可以設定在實際重置系統之前觸發。這可以透過 NMI、中斷或其他機制完成。這允許 Linux 在重置之前記錄有用的資訊(如恐慌資訊和核心核心轉儲)

pretimeout = 10;
ioctl(fd, WDIOC_SETPRETIMEOUT, &pretimeout);

請注意,預超時是指超時觸發前的時間(秒數),而不是直到預超時的時間(秒數)。例如,如果您將超時設定為 60 秒,將預超時設定為 10 秒,則預超時將在 50 秒後觸發。將預超時設定為零會停用它。

還有一個獲取預超時的函式

ioctl(fd, WDIOC_GETPRETIMEOUT, &timeout);
printf("The pretimeout was is %d seconds\n", timeout);

並非所有看門狗驅動程式都支援預超時。

獲取重啟前的秒數

一些看門狗驅動程式能夠報告系統重啟前的剩餘時間。WDIOC_GETTIMELEFT 是返回重啟前秒數的 ioctl

ioctl(fd, WDIOC_GETTIMELEFT, &timeleft);
printf("The timeout was is %d seconds\n", timeleft);

環境監控

所有看門狗驅動程式都必須返回更多系統資訊,有些進行溫度、風扇和電源級別監控,有些可以告訴您系統上次重啟的原因。GETSUPPORT ioctl 可用於詢問裝置可以做什麼

struct watchdog_info ident;
ioctl(fd, WDIOC_GETSUPPORT, &ident);

ident 結構中返回的欄位是

標識

標識看門狗驅動程式的字串

韌體版本

卡的韌體版本(如果可用)

選項

描述裝置支援的標誌

options 欄位可以設定以下位,並描述 GET_STATUS 和 GET_BOOT_STATUS ioctl 可以返回的資訊型別。

WDIOF_OVERHEAT

因 CPU 過熱而重置

機器上次由看門狗重啟,因為超過了熱限制

WDIOF_FANFAULT

風扇故障

看門狗卡監控的系統風扇發生故障

WDIOF_EXTERN1

外部繼電器 1

外部監控繼電器/源 1 被觸發。用於實際應用的控制器包含將觸發重置的外部監控引腳。

WDIOF_EXTERN2

外部繼電器 2

外部監控繼電器/源 2 被觸發

WDIOF_POWERUNDER

電源不良/電源故障

機器顯示欠壓狀態

WDIOF_CARDRESET

卡之前重置了 CPU

上次重啟是由看門狗卡引起的

WDIOF_POWEROVER

電源過壓

機器顯示過壓狀態。請注意,如果一個級別欠壓,一個級別過壓,則兩個位都將設定——這可能看起來很奇怪,但很有意義。

WDIOF_KEEPALIVEPING

保持活躍的 ping 回覆

看門狗自上次查詢以來看到了一個保持活躍的 ping。

WDIOF_SETTIMEOUT

可以設定/獲取超時時間

看門狗可以進行預超時。

WDIOF_PRETIMEOUT

預超時(秒),獲取/設定

對於那些在選項欄位中返回任何設定位的驅動程式,可以使用 GETSTATUS 和 GETBOOTSTATUS ioctl 分別查詢當前狀態和上次重啟時的狀態

int flags;
ioctl(fd, WDIOC_GETSTATUS, &flags);

or

ioctl(fd, WDIOC_GETBOOTSTATUS, &flags);

請注意,並非所有裝置都支援這兩個呼叫,有些只支援 GETBOOTSTATUS 呼叫。

一些驅動程式可以使用 GETTEMP ioctl 測量溫度。返回的值是華氏溫度

int temperature;
ioctl(fd, WDIOC_GETTEMP, &temperature);

最後,SETOPTIONS ioctl 可用於控制卡操作的某些方面

int options = 0;
ioctl(fd, WDIOC_SETOPTIONS, &options);

以下選項可用

WDIOS_DISABLECARD

關閉看門狗定時器

WDIOS_ENABLECARD

開啟看門狗定時器

WDIOS_TEMPPANIC

溫度跳閘時核心恐慌

[FIXME -- 更好的解釋]