3. 网关启动流程优化与看门狗配置

任务目标

本案例面向基于Linux的工业IoT网关,完成两项核心工作:一是通过启动脚本串行化改造与关键服务延迟加载,将网关从上电到应用就绪的时间压缩至可接受范围;二是配置硬件看门狗(以i.MX6ULL+外部看门狗芯片SP7060为例),在应用主循环中周期性喂狗,防止系统死机后无法自恢复。

环境与依赖

  • 硬件:i.MX6ULL核心板 + SP7060看门狗芯片(连接到GPIO1_IO09,低电平触发喂狗)
  • 系统:Linux 4.1.15 + Buildroot交叉编译环境
  • 关键工具:busybox(含watchdog命令)、systemd(或SysVinit,本案例使用systemd)
  • 交叉编译器:arm-linux-gnueabihf-gcc

实现方案

启动优化采用“依赖分级”策略:将启动脚本拆分为base-init(挂载文件系统、启动核心驱动)和app-init(启动业务应用)两个服务,利用systemd的After=和Type=oneshot控制顺序,避免所有服务并行争抢CPU导致启动峰值过高。看门狗部分通过设备树使能GPIO,应用层使用ioctl定时喂狗,并在异常退出时由内核驱动自动复位系统。

关键完整代码

// 文件1: /etc/systemd/system/gateway-base.service
[Unit]
Description=Gateway Base Init
DefaultDependencies=no
After=local-fs.target

[Service]
Type=oneshot
ExecStart=/usr/bin/base-init.sh
RemainAfterExit=yes

[Install]
WantedBy=sysinit.target

// 文件2: /etc/systemd/system/gateway-app.service
[Unit]
Description=Gateway Application
After=gateway-base.service network.target

[Service]
Type=simple
ExecStart=/usr/bin/gateway-app
Restart=on-failure
RestartSec=3

[Install]
WantedBy=multi-user.target

// 文件3: /usr/bin/base-init.sh
#!/bin/sh
# 挂载必要文件系统
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs devtmpfs /dev
# 加载核心驱动(按依赖顺序)
modprobe spi-imx
modprobe spidev
# 初始化看门狗GPIO
echo 9 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio9/direction
echo 1 > /sys/class/gpio/gpio9/value  # 初始拉高,禁止复位

// 文件4: /usr/bin/gateway-app.c(喂狗核心逻辑)
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/watchdog.h>

#define WDT_DEV "/dev/watchdog"
#define GPIO_FEED "/sys/class/gpio/gpio9/value"
#define FEED_INTERVAL 2  // 喂狗周期(秒)

int main() {
    int wdt_fd = open(WDT_DEV, O_WRONLY);
    if (wdt_fd < 0) {
        perror("open watchdog");
        return -1;
    }
    // 设置超时时间为5秒(硬件看门狗芯片设定)
    int timeout = 5;
    ioctl(wdt_fd, WDIOC_SETTIMEOUT, &timeout);

    int gpio_fd = open(GPIO_FEED, O_WRONLY);
    if (gpio_fd < 0) {
        perror("open gpio");
        return -1;
    }

    // 主业务循环
    while (1) {
        // 业务处理逻辑(此处简化为空转)
        usleep(100000);  // 100ms

        // 喂狗:GPIO拉低再拉高,产生下降沿触发
        write(gpio_fd, "0", 1);
        usleep(1000);
        write(gpio_fd, "1", 1);
    }
    close(wdt_fd);
    close(gpio_fd);
    return 0;
}

编译与部署

# 交叉编译应用
arm-linux-gnueabihf-gcc -o gateway-app gateway-app.c

# 部署到网关(假设通过NFS或scp)
scp gateway-app root@192.168.1.100:/usr/bin/
scp base-init.sh root@192.168.1.100:/usr/bin/
scp gateway-base.service gateway-app.service root@192.168.1.100:/etc/systemd/system/

# 在网关上执行
chmod +x /usr/bin/gateway-app /usr/bin/base-init.sh
systemctl daemon-reload
systemctl enable gateway-base.service
systemctl enable gateway-app.service
reboot

验证方法与判定标准

  1. 启动时间验证:在base-init.sh首行和gateway-app首行分别添加echo $(date +%s%N) >> /tmp/boot_time.log,重启后对比两个时间戳差值,应小于3秒(不含内核启动时间)。
  2. 看门狗功能验证:正常运行后执行kill -9 $(pidof gateway-app),观察系统应在5秒内自动重启(看门狗超时触发硬件复位)。若系统未重启,说明喂狗逻辑或GPIO配置有误。
  3. 喂狗信号检查:使用示波器测量GPIO1_IO09引脚,正常工作时应有周期约2秒的低脉冲(脉宽约1ms)。

常见问题

  • 看门狗设备不存在:确认内核已配置CONFIG_WATCHDOG和CONFIG_GPIO_WATCHDOG,且设备树中正确声明了看门狗节点。
  • 启动时间未优化:检查是否有其他服务仍在并行启动,使用systemd-analyze blame查看各服务耗时。
  • 喂狗失败导致反复重启:确认GPIO编号与硬件连接一致,且应用启动前GPIO已正确初始化为高电平。