3、QNX看门狗服务(wdog):wdog服务介绍、启动与配置、基本API函数
3.1 什么是wdog服务?
看门狗,说白了就是一个「系统保命符」。
在嵌入式系统里,最怕什么?最怕程序跑飞了、死锁了、或者某个任务卡住了。这时候如果没有看门狗,系统就彻底「凉了」。QNX的wdog服务,就是专门干这个的——它监控系统是否还活着,如果发现不对劲,就帮你重启或者执行预设的恢复动作。
我个人习惯把wdog比作「系统的心跳监护仪」。它每隔一段时间就要「听」一下系统的心跳。如果听不到了,它就认为系统出事了。
3.2 启动与配置wdog
启动wdog其实不复杂。我刚开始接触QNX时,以为这玩意儿要写一堆底层代码。后来发现,QNX已经帮你封装好了。
启动命令很简单:
# 启动wdog服务
wdog -d /dev/watchdog -t 10000 -a reboot
这里解释一下参数:
-d /dev/watchdog:指定硬件看门狗设备节点。不同板子可能不一样,我遇到过有些板子是/dev/watchdog0。-t 10000:超时时间,单位毫秒。这里设了10秒。-a reboot:超时后的动作,这里是重启。也可以设成halt或panic。
嗯,这里要注意:超时时间别设太短。我曾经在一个项目里设了2秒,结果系统稍微忙一点就被重启了。调试了一整天才发现是看门狗太敏感了。
如果你想让wdog开机自启,可以把它加到启动脚本里:
# 在/etc/system.launch中添加
wdog -d /dev/watchdog -t 15000 -a reboot
3.3 基本API函数
QNX提供了几个核心API来操作看门狗。说实话,常用的就那么几个,我列出来给你看:
| 函数名 | 作用 | 头文件 |
|---|---|---|
wdog_open() |
打开看门狗设备 | <sys/wdog.h> |
wdog_close() |
关闭看门狗设备 | <sys/wdog.h> |
wdog_kick() |
喂狗(重置定时器) | <sys/wdog.h> |
wdog_set_timeout() |
设置超时时间 | <sys/wdog.h> |
wdog_get_timeout() |
获取当前超时时间 | <sys/wdog.h> |
来看一个完整的示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wdog.h>
int main(void) {
int wd;
int ret;
// 打开看门狗
wd = wdog_open("/dev/watchdog", 0);
if (wd == -1) {
perror("wdog_open failed");
return EXIT_FAILURE;
}
printf("看门狗已打开,开始喂狗...\n");
// 主循环:每隔5秒喂一次狗
while (1) {
ret = wdog_kick(wd);
if (ret == -1) {
perror("wdog_kick failed");
break;
}
printf("喂狗成功!\n");
sleep(5);
}
// 关闭看门狗
wdog_close(wd);
return EXIT_SUCCESS;
}
这段代码的逻辑很直白:打开看门狗,然后每隔5秒喂一次。如果程序卡住了,超过10秒没喂狗,系统就会重启。
3.4 多任务环境下的喂狗策略
单任务喂狗很简单。但实际项目中,往往是多任务系统。你想想看,如果只有一个任务在喂狗,其他任务都死了,看门狗照样被喂得饱饱的——这就有问题了。
我建议的做法是:
- 主任务喂狗:一个高优先级任务专门负责喂狗。
- 健康检查:喂狗前,检查其他关键任务是否还活着。
- 心跳机制:每个关键任务定期更新一个共享变量,喂狗任务检查这些变量。
举个例子:
// 共享的心跳变量
volatile int task1_heartbeat = 0;
volatile int task2_heartbeat = 0;
// 喂狗线程
void* watchdog_thread(void* arg) {
while (1) {
// 检查所有任务的心跳
if (task1_heartbeat == 0 || task2_heartbeat == 0) {
printf("检测到任务异常,不喂狗!\n");
// 让看门狗超时触发重启
sleep(20);
} else {
wdog_kick(wd);
// 重置心跳标志
task1_heartbeat = 0;
task2_heartbeat = 0;
}
sleep(5);
}
return NULL;
}
这样做的好处是:任何一个任务挂了,看门狗都不会被喂,系统就会自动重启。我在一个车载项目中就用这个方案,效果很好。
3.5 调试技巧
调试看门狗时,最怕的就是系统反复重启,日志都来不及看。我的做法是:
- 开发阶段先禁用看门狗,或者把超时时间设得很长。
- 用
wdog_get_timeout()确认当前配置是否正确。 - 在喂狗前后加日志,记录时间戳。
还有一个实用命令:
# 查看当前看门狗状态
wdog -i /dev/watchdog
这个命令会显示超时时间、剩余时间、触发动作等信息。调试时非常有用。
好了,关于wdog服务的基本内容就这些。下一章我们会讲如何设计一个更健壮的健康监测框架,包括多级看门狗和故障恢复策略。到时候我会分享一个我在工业项目中用过的实战方案。