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