Watchdog driver API

本文深入探讨Linux系统中Watchdog的功能与实现机制,包括硬件电路、用户空间守护进程、驱动交互、定时唤醒、超时重启及预重启功能等关键概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



A Watch Timer(WDT)是一个硬件电路可以用来在系统软件发生错误的情况下reset计算机系统。

通常来说一个用户空间的daemon通过特定设备/dev/watchdog,以一定的时间间隔来通知kernel的watchdog驱动系统仍然alive。驱动然后会通知硬件设备一切正常,硬件WDT电路更新reset系统重启的timeout时间。如果用户空间失败(RAM error, kernel bug等等),那么这个通知就不会发生,硬件WDT在timeout到达后就开始重启系统。


所有的驱动都要支持最基本的操作模式:在打开/dev/watchdog后,WDT立刻就被激活了。WDT将reset系统除非每隔一定时间watchdog驱动被ping一下。这个时间间隔被称作timout或者margin。ping watchdog的最简单方法就是向WDT设备写入数据。一个非常简单的应用层watchdog daemon实现参见Documentation/watchdog/src/watchdog-simple.c


当watchdog设备节点被关闭后,如果不支持"Magic Close"功能,watchdog功能就被disable。关闭watchdog功能并不是一个好的实现方式,因为如果是watchdog daemon被不小心关闭(daemon本身的bug, 系统杀掉daemon等等),那么watchdog电路将无法重启系统。基于这个原因,许多watchdog驱动都支持内核配置选项"Disable watchdog shutdown on clost", CONFIG_WATCHDOG_NOWAYOUT. 配置这个内核选项后,那么系统一旦使能了watchdog, 这个功能将不会再被disable。但是这样又有一个问题,就是如果watchdog进程不存在的话,系统一定会重新启动,而不管是不是系统真的必须重启。


Magic Close feature:

如果驱动支持"Magic Close",那么在关闭设备文件后,驱动将不会disalbe watchdog daemon;除非在关闭前把一个特定magic 字符'V'写入watchdog设备。如果userspace daemon没有发送'V',直接关闭了文件,那么watchdog驱动会认为watchdog daemon已经死了,在给定时间内仍然没有喂狗的话就会导致WDT电路重启系统


ioctl API:

所有兼容的驱动都应该支持这个API。

使用ioctl来实现对watchdog的ping操作:

所有的驱动要支持一个ioctl操作WDIOC_KEEPALIVE,WDIOC_KEEPALIVE和write操作有相同的作用,所以watchdog daemon的主循环可以如下方式实现:

while (1) {

    inctl(fd, WDIOC_KEEPALIVE, 0);

    sleep(10);

}


Setting and getting the timeout:

对于某些驱动,支持在watchdog运行时通过WDIOC_SETTIMEOUT修改timeout,这些驱动的option域设置了WDIOF_SETTIMEOUT标志。这个ioctl操作的参数是一个整数,代表timeout秒数。驱动通过这个参数返回当前设置后timeout,由于硬件电路的限制,这个timeout和请求设置的timeout可能并不相同。

从linux kernel2.4.18开始,增加了GETTIMEOUT ioctl来查询当前的timeout值


Pretimeouts:

有些watchdog支持在重启计算机前某一时间点上,设置一个触发机关。可以通过NMI, interrupt或者其他机制实现。这样允许系统在reset前记录有用的信息(比如panic信息和kernel coredumps)。

pretimeout = 10;

ioctl(fd, WDIOC_SETPRETIMEOUT, &pretimeout);

注意pretimeout是触发时间到系统重启时间点的长度。比如,如果你设置timeout为60, pretimeout为10,那么在50秒的时候(重启之前的 10秒)将触发机关。

操作WDIOC_GETPRETIMEOUT用来获取设置的pretimeout:

ioctl(fd, WDIOC_GETPRETIMEOUT, &timeout);

不是所有的watchdog驱动都支持pretimeout


获取watchdog距离重启的秒数

一些驱动支持获取系统watchdog重启需要的秒数,WDIOC_GETTIMELEFT ioctl用来实现这个功能

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

环境监测

所有的驱动要求能够返回watchdog系统的一些信息,GETSUPPORT ioctl用来查询设备可以支持哪些信息查询

转自:http://blog.csdn.net/kickxxx/article/details/8082847

### TPL5010 Watchdog Timer Code Implementation Example For implementing a watchdog timer using the TPL5010 device, one must consider how memory allocation and context handling interact with hardware initialization and periodic resets. When dealing with USB-related operations or similar contexts where atomicity is required, specific flags like `GFP_ATOMIC` should be used when allocating memory within interrupt handlers or other non-process contexts[^2]. Below is an illustrative C code snippet demonstrating basic setup procedures for initializing and managing a watchdog timer based on the TPL5010 chip: ```c #include <linux/watchdog.h> #include <linux/module.h> #include <linux/i2c.h> #define WATCHDOG_TIMEOUT 60 /* Timeout value in seconds */ static struct i2c_client *client; static unsigned int timeout = WATCHDOG_TIMEOUT; /* Function prototypes */ static int tpl5010_start(struct watchdog_device *); static int tpl5010_stop(struct watchdog_device *); struct watchdog_ops tpl5010_wdt_ops = { .owner = THIS_MODULE, .start = tpl5010_start, .stop = tpl5010_stop, }; struct watchdog_info ident = { .identity = "TPL5010 WDT", .firmware_version= 1, .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, }; static struct watchdog_device wdd = { .info = &ident, .ops = &tpl5010_wdt_ops, .timeout = WATCHDOG_TIMEOUT, }; // Start watchdog functionality. static int tpl5010_start(struct watchdog_device *wdev) { // Write command to start watchdog via I²C interface... } // Stop watchdog operation. static int tpl5010_stop(struct watchdog_device *wdev) { // Send stop command through I²C bus... } static int __init tpl5010_init(void) { int ret; client = ... ; // Initialize I²C client here... if ((ret = watchdog_register_device(&wdd)) != 0) { pr_err("Failed to register watchdog device.\n"); return ret; } pr_info("TPL5010 watchdog driver loaded successfully!\n"); return 0; } module_init(tpl5010_init); static void __exit tpl5010_exit(void) { watchdog_unregister_device(&wdd); pr_info("TPL5010 watchdog driver unloaded.\n"); } module_exit(tpl5010_exit); MODULE_LICENSE("GPL"); ``` This example assumes familiarity with Linux kernel programming concepts such as module registration, watchdog API usage, and I²C communication protocols.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值