1. IIoT网关开发环境搭建与最小可运行框架

IIoT网关开发环境搭建与最小可运行框架 学习卡片

任务目标

在 Linux 主机上搭建可交叉编译到 ARM 目标板的开发环境,并编写一个最小 IIoT 网关程序:启动后打印版本、设备 ID、监听端口等启动日志,然后进入主循环等待退出信号。程序需能在主机本地编译运行验证,也能用交叉工具链编译出 ARM 可执行文件。

环境与依赖

  • 主机:Ubuntu/Debian 类 Linux,安装 build-essential、gcc、make。
  • 交叉工具链:gcc-arm-linux-gnueabihf(ARMv7 硬浮点,常见于工业网关/树莓派类板卡)。
  • 目标板:运行 Linux 的 ARM 设备,具备串口或 SSH 用于部署。
sudo apt update
sudo apt install -y build-essential gcc-arm-linux-gnueabihf

最小框架代码

单文件 gateway.c,包含配置结构、启动日志、信号处理与主循环。用 #ifdef 区分主机与目标板编译,交叉编译时通过 -DTARGET_ARM 打开。

/* gateway.c - IIoT 网关最小可运行框架 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#define GW_VERSION "0.1.0"

typedef struct {
    const char *device_id;
    int         listen_port;
    int         poll_interval_ms;
} gw_config_t;

static volatile sig_atomic_t g_running = 1;

static void on_signal(int sig) {
    (void)sig;
    g_running = 0;
}

static void print_banner(const gw_config_t *cfg) {
    printf("========================================\n");
    printf(" IIoT Gateway starting\n");
    printf(" version      : %s\n", GW_VERSION);
    printf(" device_id    : %s\n", cfg->device_id);
    printf(" listen_port  : %d\n", cfg->listen_port);
    printf(" poll_interval: %d ms\n", cfg->poll_interval_ms);
#ifdef TARGET_ARM
    printf(" build target : ARM (cross-compiled)\n");
#else
    printf(" build target : HOST (native)\n");
#endif
    printf("========================================\n");
}

int main(int argc, char **argv) {
    gw_config_t cfg = {
        .device_id        = "gw-001",
        .listen_port      = 5020,
        .poll_interval_ms = 1000,
    };

    /* 允许命令行覆盖设备 ID,便于多实例部署 */
    if (argc > 1) cfg.device_id = argv[1];

    signal(SIGINT,  on_signal);
    signal(SIGTERM, on_signal);

    print_banner(&cfg);
    printf("[gw] entering main loop, press Ctrl+C to stop\n");

    while (g_running) {
        /* 真实网关在此处轮询 Modbus/OPC UA 等设备并上报 */
        printf("[gw] heartbeat device=%s port=%d\n",
               cfg.device_id, cfg.listen_port);
        usleep(cfg.poll_interval_ms * 1000);
    }

    printf("[gw] shutdown, bye\n");
    return 0;
}

构建与运行

主机本地编译运行,验证逻辑正确:

gcc -Wall -O2 -o gateway_host gateway.c
./gateway_host gw-test

交叉编译到 ARM 目标板:

arm-linux-gnueabihf-gcc -Wall -O2 -DTARGET_ARM -o gateway_arm gateway.c
file gateway_arm   # 应显示 ARM, EABI5, hard-float

部署到目标板(示例用 scp,实际可用串口/U 盘):

scp gateway_arm root@<board-ip>:/usr/local/bin/gateway
ssh root@<board-ip> '/usr/local/bin/gateway gw-001'

验证方法与通过条件

  1. 主机运行 ./gateway_host gw-test,应看到 banner 中 device_id=gw-test、build target : HOST,随后每秒打印一次 heartbeat。
  2. 按 Ctrl+C 后应打印 [gw] shutdown, bye 并正常退出(退出码 0)。
  3. file gateway_arm 输出包含 ARM 与 hard-float,说明交叉编译成功。
  4. 目标板上运行 gateway_arm,banner 中 build target : ARM (cross-compiled),heartbeat 正常输出,Ctrl+C 可退出。

以上四条全部满足即视为本案例通过。

常见问题

  • 交叉编译报 arm-linux-gnueabihf-gcc: not found:确认已安装 gcc-arm-linux-gnueabihf,或按目标板 ABI 换成 aarch64-linux-gnu-gcc。
  • 目标板运行报 No such file or directory:多为动态链接器不匹配,可加 -static 重新编译。
  • heartbeat 不打印:检查 usleep 参数单位(微秒),以及 stdout 是否被重定向缓冲,可加 setvbuf(stdout, NULL, _IONBF, 0)。