4. 看门狗超时处理:超时机制、默认动作(复位/中断)、自定义超时回调函数
看门狗的核心价值,说白了就是「超时了怎么办」。
很多初学者以为看门狗超时就是直接复位,其实没那么简单。QNX 给了我们好几层选择,从粗暴的硬件复位,到优雅的中断通知,再到完全自定义的处理逻辑。我个人习惯把这三层叫做「三级响应机制」——你想想看,不同场景下,我们需要的处理方式肯定不一样。
4.1 超时机制:从「喂狗」到「咬人」
看门狗的超时机制,本质上是一个倒计时器。你喂一次狗,计数器就重置到初始值。如果计数器减到0,看门狗就「咬人」了。
在 QNX 中,超时时间是通过 WatchdogCreate() 或 devctl() 设置的。我记得有一次调试一个工业控制器,客户说设备偶尔会死机,但看门狗从来没触发过。后来发现是超时时间设得太长了——30秒,而系统卡死通常只持续5秒就恢复了。嗯,这里要注意:超时时间不是越长越好,也不是越短越好。
超时机制有几个关键参数:
- 初始超时值:喂狗后重置到的计数值
- 当前计数值:正在递减的计数器
- 超时动作:计数器到0后执行的操作
- 喂狗间隔:两次喂狗之间的最大允许时间
这些参数在 QNX 的 sigevent 结构中定义。我刚开始用的时候,总觉得这个结构体字段太多,后来发现其实核心就两个:触发条件和触发后的动作。
4.2 默认动作:复位 vs 中断
QNX 看门狗默认支持两种超时动作:系统复位和中断触发。这两种方式各有各的适用场景。
| 特性 | 复位模式 | 中断模式 |
|---|---|---|
| 触发后果 | 直接硬件复位 | 触发一个中断信号 |
| 恢复方式 | 系统重新启动 | 在中断服务程序中处理 |
| 适用场景 | 严重故障、安全关键系统 | 临时故障、可恢复错误 |
| 数据保存 | 无法保存,直接重启 | 可以在中断中保存关键数据 |
| 调试难度 | 低,但信息丢失 | 高,可以记录故障现场 |
复位模式是最常见的。说白了就是「死透了,重新来」。我在做车载项目时,安全相关的模块必须用复位模式——比如刹车控制器,一旦超时,必须立即复位,不能有任何犹豫。
中断模式则更灵活。超时后先触发一个中断,让你有机会做最后的处理。我曾经在一个数据采集系统中用过这个模式:看门狗超时了,但我不想直接复位,因为还有一批数据没写到Flash里。在中断服务程序里,我把缓存数据紧急写入,然后再手动触发复位。
4.3 自定义超时回调函数
QNX 最强大的地方在于,你可以完全自定义超时后的行为。通过 sigevent 结构,你可以指定一个回调函数,看门狗超时后自动调用它。
这个回调函数运行在什么上下文中?嗯,这里要讲清楚:它运行在中断上下文。所以你的回调函数必须非常轻量,不能做阻塞操作,不能申请内存,不能调用 printf 这类重型函数。
来看一个实际例子:
#include <sys/siginfo.h>
#include <hw/inout.h>
// 自定义超时回调函数
void my_watchdog_handler(sigevent *event) {
// 注意:这里运行在中断上下文!
// 只能做轻量操作
// 记录故障原因到寄存器
uint32_t *fault_reg = (uint32_t *)0xFFFF0000;
*fault_reg = 0xDEADBEEF;
// 保存关键上下文
// 这里不能调用 printf、malloc 等
// 触发系统复位
// 或者做其他自定义处理
}
int setup_custom_watchdog() {
int fd;
sigevent event;
// 打开看门狗设备
fd = open("/dev/watchdog0", O_RDWR);
if (fd == -1) {
return -1;
}
// 配置自定义事件
SIGEV_FUNCTION_INIT(&event, my_watchdog_handler, NULL);
// 设置看门狗参数
devctl(fd, WDIOCSETEVENT, &event, sizeof(event), NULL);
return fd;
}
这段代码里,SIGEV_FUNCTION_INIT 宏是关键。它把我们的回调函数 my_watchdog_handler 注册到了看门狗的事件系统中。超时发生后,QNX 内核会直接调用这个函数。
4.4 实际项目中的选择策略
说了这么多,到底该用哪种方式?我根据多年经验,总结了一个简单的决策树:
- 系统是否安全关键?(比如汽车、医疗设备)→ 用复位模式
- 是否需要保存故障现场?→ 用中断模式或自定义回调
- 故障是否可以恢复?→ 可恢复用中断,不可恢复用复位
- 调试阶段还是生产阶段?→ 调试用中断,生产用复位
我曾经犯过一个错误:在生产环境中用了中断模式,结果看门狗频繁触发中断,但系统并没有复位,导致故障不断累积,最后整个系统崩溃得更惨。从那以后,我对生产环境的看门狗策略就变得非常保守——能用复位就用复位。
4.5 总结一下
看门狗超时处理,说白了就是「什么时候咬人,怎么咬」。QNX 给了你三个层次的选择:
- 复位模式:简单粗暴,适合安全关键系统
- 中断模式:灵活可控,适合需要故障记录的场合
- 自定义回调:最大自由度,但需要你小心使用
我个人建议:新手先用复位模式,等你对系统行为足够了解了,再尝试中断和自定义回调。毕竟,看门狗是最后一道防线,别让它成为新的故障源。