喂狗策略:定时喂狗 vs 条件喂狗

看门狗这东西,说白了就是给系统上的一道保险。但保险怎么上,上得合不合理,这里头门道不少。我做了十几年嵌入式,见过太多「狗叫了」的惨案——有的是真死机,有的纯粹是喂狗策略没设计好。

今天咱们聊聊两种主流的喂狗策略:定时喂狗条件喂狗。别小看这个选择,选错了,你的系统可能天天复位,或者该复位的时候它反而不动了。

定时喂狗:简单粗暴,但别乱用

定时喂狗,就是开个定时器,每隔固定时间去踢一下狗。比如每100ms喂一次,狗的超时时间设成200ms。这样只要系统还在跑,狗就不会叫。

优点很明显:实现简单,代码量少,适合裸机或简单任务系统。

缺点也很致命:它只能检测到「完全不跑」的情况。如果系统陷入死循环,但中断还能响应,那定时器照常喂狗,狗就睡着了。

核心要点:定时喂狗检测的是「系统是否还在运行」,而不是「系统是否正常工作」。

我记得有一次做工业网关,用了定时喂狗。结果某个外设驱动出了bug,导致主循环卡在了一个while里。但定时器中断还在跑,狗一直喂着,系统就是不复位。最后是现场工程师发现设备不响应了,手动断电重启的。嗯,从那以后我对定时喂狗就多留了个心眼。

条件喂狗:更智能,但更复杂

条件喂狗,是在关键任务执行完毕后,才去喂狗。比如:

  • 采集完传感器数据后喂一次
  • 完成通信处理后喂一次
  • 执行完控制算法后喂一次

这样做的好处是:如果某个关键任务卡住了,狗就没人喂,系统自动复位。

你想想看,这就像你请了个监工。监工不是每隔几分钟来看你一眼,而是等你干完一件活才来检查。你干不完活,他就叫人来换你。

我的建议:条件喂狗更适合对实时性要求高、任务链路清晰的系统。比如工业PLC、运动控制器这类设备。

但条件喂狗有个坑——喂狗点太多,容易乱。我曾经在一个项目里,条件喂狗点散布在七八个函数里。结果调试时发现,某个异常路径把喂狗给跳过了,系统莫名其妙地复位。查了两天才找到原因。

两种策略的对比

对比项 定时喂狗 条件喂狗
实现难度 中高
检测粒度 粗(只检测运行) 细(检测任务完成)
误复位风险 中(喂狗点遗漏)
适用场景 裸机、简单任务 多任务、复杂系统

多任务系统中的喂狗位置选择

到了RTOS或者Linux这种多任务系统里,喂狗的位置就更讲究了。你不能随便找个任务就喂,也不能所有任务都喂。这里头有个平衡问题。

喂狗位置的三条铁律

我个人习惯把喂狗位置分成三个层级,你可以参考一下:

  1. 最低优先级任务中喂狗:这是底线。如果最低优先级的任务还能跑,说明系统至少没完全死掉。
  2. 关键任务完成后喂狗:比如通信任务、控制任务。这些任务挂了,系统功能就废了。
  3. 空闲任务中喂狗:这是最后一道防线。空闲任务能跑,说明调度器还活着。

注意:千万不要在中断服务函数里喂狗!我见过有人这么干,结果主任务全卡死了,中断还在喂狗,系统永远不复位。这相当于把看门狗给废了。

实际项目中的喂狗策略

我最近做的一个工业控制器项目,用了FreeRTOS,任务有5个:

  • 通信任务(高优先级)
  • 控制任务(中优先级)
  • 采集任务(中优先级)
  • 显示任务(低优先级)
  • 空闲任务(最低)

喂狗策略是这样的:

// 伪代码示例
void task_communication(void) {
    while(1) {
        // 处理通信数据
        process_comm();
        // 通信完成后喂狗
        feed_watchdog();
        vTaskDelay(10);
    }
}

void task_control(void) {
    while(1) {
        // 执行控制算法
        execute_control();
        // 控制完成后喂狗
        feed_watchdog();
        vTaskDelay(20);
    }
}

void task_idle(void) {
    while(1) {
        // 空闲时也喂狗,作为保底
        feed_watchdog();
        vTaskDelay(100);
    }
}

你看,通信和控制任务各自喂狗,空闲任务也喂。这样即使通信任务挂了,控制任务还能喂;两个都挂了,空闲任务还能撑一会儿。但空闲任务的喂狗间隔设得长一些,避免掩盖问题。

避坑指南:我曾经踩过的坑

我曾经在一个项目里,把所有喂狗操作都放在了一个单独的低优先级任务里。结果高优先级任务死锁了,低优先级任务根本抢不到CPU,狗就饿死了。系统反复复位,现场工程师差点把设备砸了。

后来我改成每个关键任务自己喂狗,问题就解决了。所以我的建议是:喂狗点要分散,不要集中

总结一下

  • 定时喂狗适合简单系统,条件喂狗适合复杂系统
  • 多任务系统中,喂狗点要分布在关键任务里
  • 不要在中断里喂狗
  • 喂狗间隔要合理,太短浪费CPU,太长可能错过复位时机

嗯,关于喂狗策略,今天就聊这么多。这些经验都是真金白银换来的,你下次做项目时可以参考一下。

喂狗策略知识体系 喂狗策略 定时喂狗 条件喂狗 实现简单,适合裸机系统 只能检测「是否运行」 误复位风险低 检测任务完成度 适合多任务复杂系统 喂狗点需精心设计 多任务系统喂狗位置选择 最低优先级任务 关键任务完成后 空闲任务中 ❌ 中断中喂狗

公众号:蓝海资料掘金营,微信deep3321