一、简介:为什么AI系统必须“养狗”?

  • AI推理程序常占用整卡/整核,一旦陷入死循环、死锁或内存泄漏,SSH失联、日志断更、kill -9无响应——重启是唯一恢复手段。

  • 工业现场无人值守(边缘盒子、机械臂控制器、车载ECU),人工重启成本>¥1000/次

  • 硬件看门狗(Watchdog Timer, WDT)= 最后一道保险:
    在规定窗口(如5s)内未收到“喂狗”脉冲,直接拉低RESET引脚,整机重启,不受内核僵死影响

  • 软件守护进程= 策略层:监控AI主程序健康状态(PID存活、GPU利用率、业务心跳),综合决策是否喂狗

掌握“软硬联合喂狗”设计,可让AI产品在客户现场7×24h不死机,显著提升可靠性指标(MTBF↑、MTTR↓)。


二、核心概念:5个关键词先搞懂

名词 一句话说明 本文出现形式
Watchdog Timer 硬件倒计时器,超时触发系统复位 /dev/watchdog
喂狗(Kick/Pet) 在倒计时归零前写特定字符,重置计数器 echo 1 > /dev/watchdog
心跳(Heartbeat) AI主程序周期性向守护进程发送“我还活着”信号 UNIX域socket /tmp/ai.sock
守护进程(Daemon) 高优先级实时任务,负责监控+喂狗 SCHED_FIFO:90
安全超时窗 喂狗间隔<WDT额定时间×80%,留余量 WDT=5s → 喂狗周期≤4s

三、环境准备:10分钟搭好“看门狗实验室”

1. 硬件

  • 任意x86_64主板(Intel/AMD均可)→ 自带SuperIO WDT

  • 或树莓派4B → Broadcom BCM2711 WDT

  • 预留串口,用于强制故障注入(echo 死循环)

2. 软件

组件 版本 安装命令
Ubuntu Server 22.04 sudo apt update
PREEMPT_RT内核 5.15-rt 见下文脚本
GCC ≥9.0 sudo apt install gcc make
  • 一键安装RT内核(可复制)

#!/bin/bash
# install_rt.sh
wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.15.71/linux-image-5.15.71-rt53-generic_amd64.deb
wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.15.71/linux-headers-5.15.71-rt53-generic_amd64.deb
sudo dpkg -i linux*.deb && sudo update-grub && sudo reboot

3. 创建实验目录

mkdir -p ~/watchdog-lab && cd ~/watchdog-lab

四、应用场景(300字)

边缘AI质检工控机中,GPU运行YOLOv5实时检测传送带缺陷,要求漏检率<0.1%系统无人工干预连续运行>30天。某日因多线程bug,AI主线程卡在pthread_mutex_lock死锁,GPU利用率归零,TCP心跳中断。由于现场无显示器,运维人员次日才发现停线,导致3小时停产损失¥18万。引入“软硬看门狗”后:
①守护进程每2s检查AI心跳与GPU利用率,任一指标异常即停止喂狗
②硬件WDT5s超时触发整机复位;
③BIOS上电自启动AI程序,3分钟内产线恢复,MTTR从数小时缩短到分钟级,全年零人工重启记录


五、实际案例与步骤:从零编写“喂狗守护+AI心跳”

5.1 硬件看门狗驱动确认

# 查看是否已加载
lsmod | grep watchdog
# 应该出现 iTCO_wdt 或 bcm2835_wdt
# 设备节点
ls -l /dev/watchdog

若无节点,手动加载:

sudo modprobe iTCO_wdt   # Intel主板
sudo modprobe bcm2835_wdt # 树莓派

5.2 AI主程序:带心跳的推理循环(简化版)

/* ai_main.c */
#include <stdio.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#define HEARTBEAT_PATH "/tmp/ai.sock"
static int hb_fd;

void heartbeat_init(void){
    hb_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
    struct sockaddr_un addr = {.sun_family = AF_UNIX};
    strncpy(addr.sun_path, HEARTBEAT_PATH, sizeof(addr.sun_path)-1);
    connect(hb_fd, (struct sockaddr*)&addr, sizeof(addr));
}

void heartbeat_send(void){
    static uint32_t seq = 0;
    send(hb_fd, &seq, sizeof(seq), 0);
    seq++;
}

int main(void){
    heartbeat_init();
    /* 模拟推理循环 */
    for(;;){
        usleep(1000000);   /* 1s 推理一次 */
        heartbeat_send();  /* 告诉守护进程:我还活着 */
        printf("AI: inference done, seq=%u\n", seq);
    }
}

编译:

gcc ai_main.c -o ai_main

5.3 守护进程:实时优先级喂狗逻辑

/* watchdog_daemon.c */
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <linux/watchdog.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>

#define HEARTBEAT_PATH "/tmp/ai.sock"
#define WDT_DEV        "/dev/watchdog"
#define SAFE_TIMEOUT   2          /* 喂狗周期 < WDT默认5s */
#define GPU_UTIL_MIN   5          /* GPU最低利用率 % */

static int wdt_fd, hb_fd;
static uint32_t last_seq = 0;
static time_t   last_t;

/* 设置实时优先级 */
static void set_realtime(void){
    struct sched_param param = { .sched_priority = 90 };
    pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
}

/* 打开硬件看门狗 */
static int wdt_init(void){
    wdt_fd = open(WDT_DEV, O_WRONLY);
    if(wdt_fd < 0){ perror("open watchdog"); exit(1); }
    int timeout = 5;
    ioctl(wdt_fd, WDIOC_SETTIMEOUT, &timeout);
    printf("WDT timeout set to %ds\n", timeout);
    return wdt_fd;
}

/* 喂狗一次 */
static void kick_dog(void){
    write(wdt_fd, "\0", 1);
}

/* 非阻塞接收心跳 */
static int recv_heartbeat(void){
    uint32_t seq;
    if(recv(hb_fd, &seq, sizeof(seq), MSG_DONTWAIT) == sizeof(seq)){
        last_seq = seq;
        last_t   = time(NULL);
        return 1;
    }
    return 0;
}

/* 简易GPU利用率检查(解析 nvidia-smi) */
static int gpu_util_ok(void){
    FILE *fp = popen("nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits", "r");
    if(!fp) return 1; /* 没有GPU则跳过 */
    int util = 0;
    fscanf(fp, "%d", &util);
    pclose(fp);
    return util >= GPU_UTIL_MIN;
}

int main(void){
    set_realtime();
    wdt_init();
    /* 创建 UNIX 域 socket 接收心跳 */
    hb_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
    struct sockaddr_un addr = {.sun_family = AF_UNIX};
    strncpy(addr.sun_path, HEARTBEAT_PATH, sizeof(addr.sun_path)-1);
    unlink(HEARTBEAT_PATH);
    bind(hb_fd, (struct sockaddr*)&addr, sizeof(addr));
    /* 主循环 */
    for(;;){
        sleep(SAFE_TIMEOUT);
        int hb_ok  = recv_heartbeat() || (time(NULL) - last_t < SAFE_TIMEOUT);
        int gpu_ok = gpu_util_ok();
        if(hb_ok && gpu_ok){
            kick_dog();
            printf("KICK dog - HB:%d GPU:%d\n", hb_ok, gpu_ok);
        }else{
            printf("STOP kick - HB:%d GPU:%d → 即将复位!\n", hb_ok, gpu_ok);
            /* 可选:留 1s 日志落盘 */
            sleep(1);
            /* 不再喂狗,WDT将复位系统 */
        }
    }
}

编译:

gcc watchdog_daemon.c -o watchdog_daemon -pthread

5.4 运行与验证

  1. 启动守护进程(需 root)

sudo ./watchdog_daemon &
  1. 启动 AI 程序

./ai_main
  1. 观察喂狗日志

KICK dog - HB:1 GPU:15
KICK dog - HB:1 GPU:14
  1. 模拟死锁(另开终端)

sudo gdb -p $(pidof ai_main)
(gdb) set var some_mutex = 1   # 随意制造死锁
(gdb) quit
  1. 守护进程 2s 后检测不到心跳,停止喂狗 → 约 3s 后系统硬件重启,串口可见 BIOS 重新上电信息。


六、常见问题与解答(FAQ)

问题 现象 解决
/dev/watchdog 打不开 Permission denied 守护进程必须用 root 运行;或加 udev 规则 MODE=0666
系统无限重启 刚开机就复位 检查守护进程是否未启动;BIOS 里可暂时关闭 WDT
GPU 利用率检测失败 nvidia-smi 不存在 改用 intel_gpu_top 或跳过 GPU 检查分支
心跳包乱码 收到非 4 字节数据 在协议里加 magic number 或 JSON 校验
cyclictest 延迟高 喂狗周期不稳 给守护进程 SCHED_FIFO:95 并绑定 isolcpus

七、实践建议与最佳实践

  1. 双看门狗策略
    硬件 WDT + 软件 softdog 模块双保险,防止硬件故障遗漏。

  2. 余量设计
    WDT 额定 5s → 喂狗周期≤2s,留 60% 余量抵御调度抖动。

  3. 日志落盘
    停止喂狗前用 sync() 强制写日志,方便事后根因分析。

  4. 灰度验证
    先在测试机注入 100 次死锁,确认 100 次重启成功,再上线产线。

  5. 与 systemd 集成
    守护进程提供 systemd unit,支持 Restart=always,掉电自启。

  6. 监控指标导出
    通过 node_exporter 暴露 watchdog_kick_total 指标,Prometheus 告警“连续 10s 无 kick”。


八、总结:一张脑图带走全部要点

看门狗联合设计
├─ 硬件 WDT:/dev/watchdog,超时复位
├─ 守护进程:SCHED_FIFO,监控心跳+GPU
├─ AI 心跳:UNIX 域 socket,每秒广播
├─ 故障注入:gdb 死锁、stress 满载
└─ 验证:cyclictest 确认实时性,100 次重启 0 失败

掌握“软硬联合喂狗”,你的 AI 系统就多了一条“不死金身”——
无论死锁、死循环、内存泄漏,3 秒内必重启,3 分钟内业务恢复,真正做到7×24h 无人值守

立刻打开实验机,复制本文代码跑一遍,再把守护进程打包进 Yocto 或 Buildroot,让下一个客户再也见不到“AI卡死”的投诉

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐