Linux 看门狗驱动程序 API

上次审查:2007/05/10

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

本文档的部分内容逐字复制自 sbc60xxwdt 驱动程序,该驱动程序版权归 2000 Jakob Oestergaard <jakob@ostenfeld.dk> 所有

本文档描述了 Linux 2.4.18 内核的状态。

简介

看门狗定时器 (WDT) 是一种硬件电路,可以在发生软件故障时重置计算机系统。您可能已经知道了。

通常,用户空间守护程序会通过 /dev/watchdog 特殊设备文件定期通知内核看门狗驱动程序,用户空间仍然处于活动状态。当发生此类通知时,驱动程序通常会告诉硬件看门狗一切正常,并且看门狗应该再等待一小段时间才能重置系统。如果用户空间失败(RAM 错误、内核错误等),则通知将停止发生,并且硬件看门狗将在超时发生后重置系统(导致重新启动)。

Linux 看门狗 API 是一种相当临时的结构,不同的驱动程序实现了不同的,有时是不兼容的部分。此文件试图记录现有用法,并允许未来的驱动程序编写者将其用作参考。

最简单的 API

所有驱动程序都支持基本操作模式,其中看门狗在 /dev/watchdog 打开后立即激活,并且除非在一定时间内 ping 看门狗,否则会重新启动,此时间称为超时或裕量。ping 看门狗的最简单方法是将一些数据写入设备。因此,一个非常简单的看门狗守护程序将如下所示的源文件:请参阅 samples/watchdog/watchdog-simple.c

更高级的驱动程序可以例如在执行写入调用以 ping 看门狗之前检查 HTTP 服务器是否仍在响应。

当设备关闭时,看门狗将被禁用,除非支持“魔术关闭”功能(见下文)。这并不总是一个好主意,因为如果看门狗守护程序中存在错误并且它崩溃,系统将不会重新启动。因此,一些驱动程序支持配置选项“在关闭时禁用看门狗关闭”,CONFIG_WATCHDOG_NOWAYOUT。如果在编译内核时将其设置为 Y,则一旦启动看门狗,就无法禁用它。因此,如果看门狗守护程序崩溃,系统将在超时经过后重新启动。看门狗设备通常还支持 nowayout 模块参数,以便可以在运行时控制此选项。

魔术关闭功能

如果驱动程序支持“魔术关闭”,则除非在关闭文件之前向 /dev/watchdog 发送特定的魔术字符“V”,否则驱动程序将不会禁用看门狗。如果用户空间守护程序在不发送此特殊字符的情况下关闭文件,则驱动程序将假定守护程序(以及一般的用户空间)已死,并将停止 ping 看门狗,而不会首先禁用它。如果看门狗没有在足够的时间内重新打开,这将导致重新启动。

ioctl API

所有符合标准的驱动程序也都支持 ioctl API。

使用 ioctl ping 看门狗

所有具有 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 在重置之前记录有用的信息(如 panic 信息和内核核心转储)

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

请注意,预超时是超时时间之前的时间秒数。它不是预超时之前的秒数。因此,例如,如果您将超时设置为 60 秒,并将预超时设置为 10 秒,则预超时将在 50 秒后触发。将预超时设置为零会禁用它。

还有一个用于获取预超时的 get 函数

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 结构中返回的字段为

身份

标识看门狗驱动程序的字符串

firmware_version

如果可用,则为卡的固件版本

options

描述设备支持的标志

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

温度跳闸时的内核 panic

[FIXME -- 更好的解释]