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 -- 更好的解释]