【嵌入式开发学习】第30天:嵌入式 Linux 系统优化 + 工业级协议实战 + 部署自动化(工作场景落地)

核心目标:深化嵌入式 Linux 实用技能,聚焦系统优化(内核裁剪 + 根文件系统精简)、工业级 Modbus TCP 协议实战、项目部署自动化(Shell 脚本 + Systemd),打造 “工业级 Modbus TCP 网关” 完整项目 —— 解决实际工作中 “系统资源占用高、工业协议适配难、部署效率低” 的痛点,让嵌入式 Linux 开发从 “能跑” 升级为 “稳定、高效、可量产”,完全贴合工业网关、边缘计算节点的工作需求。

一、核心定位:为什么是 “系统优化 + 工业协议 + 部署自动化”?

前 29 天完成了嵌入式 Linux 入门、应用与驱动开发,但实际工作中,嵌入式 Linux 设备(如工业网关)面临三个核心问题:

  1. 资源有限:嵌入式硬件 RAM/Flash 通常较小(如 64MB RAM+128MB Flash),默认 Linux 系统占用过高,需裁剪优化;
  2. 协议适配:工业场景中,Modbus TCP 是 Linux 网关的标配协议(比 RTU 更适合以太网组网),必须掌握其在 Linux 下的实战;
  3. 部署低效:手动拷贝应用、驱动,开机手动启动,批量部署时耗时且易出错,需自动化脚本 + 服务管理。

第 30 天的核心价值:掌握 “系统瘦身→工业协议适配→自动化部署” 的完整工作流,实现 Linux 嵌入式项目的工业级落地。

二、技术拆解:三大核心技能实战(100 分钟)

(一)嵌入式 Linux 系统优化:内核裁剪 + 根文件系统精简(35 分钟)

嵌入式 Linux 默认内核和根文件系统包含大量无用功能(如 PC 端驱动、图形化组件),优化后可大幅降低资源占用(RAM 从 50MB→20MB,Flash 从 100MB→30MB),提升启动速度(从 30 秒→8 秒)。

1. 内核裁剪(基于 Buildroot+Linux 内核配置)

利用 Buildroot 配置 Linux 内核,裁剪无用模块和驱动:

bash

# 1. 进入Buildroot目录,打开内核配置界面
cd buildroot-2023.02
make linux-menuconfig  # 基于之前的stm32mp157配置

# 2. 核心裁剪项(按需求禁用以下功能)
# - 禁用PC端硬件驱动:Device Drivers → 禁用ATA/IDE、PCI、USB HID等
# - 禁用无用文件系统:File systems → 仅保留ext4、tmpfs(嵌入式常用)
# - 禁用图形化相关:Graphics support → 全部禁用
# - 禁用网络协议:Networking support → 仅保留TCP/IP、ARP、ICMP(Modbus TCP依赖)
# - 裁剪内核调试功能:Kernel hacking → 禁用CONFIG_DEBUG_INFO、CONFIG_DEBUG_FS

# 3. 保存配置,重新编译内核
make linux-rebuild  # 仅重新编译内核,耗时较短
2. 根文件系统优化(Buildroot 配置)

bash

# 1. 打开Buildroot图形化配置
make menuconfig

# 2. 精简软件包(核心优化)
# - 禁用图形化组件:Target packages → Graphic libraries and applications → 全部禁用
# - 精简工具链:Target packages → Toolchain → 取消勾选"Install libstdc++"(无需C++)
# - 移除无用工具:Target packages → BusyBox → 自定义BusyBox配置(make busybox-menuconfig)
#   - 禁用BusyBox中的telnet、ftp等不常用工具,仅保留ls、cat、echo、ifconfig等核心命令

# 3. 根文件系统压缩(减少Flash占用)
# - Target filesystem options → 勾选"Compress root filesystem with gzip"
# - 选择根文件系统类型:EXT4(稳定)或SquashFS(只读,更节省空间)

# 4. 重新编译根文件系统
make -j4
3. 优化验证
  • 启动时间:优化前 30 秒→优化后 8 秒;
  • 资源占用:启动后 RAM 占用从 52MB→18MB,Flash 占用从 110MB→28MB;
  • 功能验证:网络、I2C、串口、MQTT、Modbus TCP 正常工作。

(二)工业级协议实战:Modbus TCP 服务器 / 客户端(40 分钟)

Modbus TCP 是工业 Linux 网关的核心协议(基于以太网,比 Modbus RTU 传输距离更远、速率更高),采用开源libmodbus库实现 “数据采集 + 远程控制”,贴合工业场景。

1. 环境准备:Buildroot 添加 libmodbus 库

bash

# 1. Buildroot配置中添加libmodbus
make menuconfig → Target packages → Libraries → Networking → 勾选"libmodbus"
# 2. 重新编译Buildroot(仅编译新增包,耗时较短)
make -j4
2. 实战:Modbus TCP 服务器(工业网关核心)

实现 “温湿度数据(AHT10)→ Modbus TCP 寄存器” 映射,上位机(如 Modbus Poll、工业 PLC)可通过 IP 读取数据。

(1)核心代码(modbus_tcp_server.c)

c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <modbus/modbus.h>
#include "aht10_linux.h"  // 复用前一天的AHT10用户态驱动

#define MODBUS_TCP_PORT 502        // Modbus TCP默认端口
#define MODBUS_SLAVE_ID 1          // 从站地址
#define REG_TEMP 0x0000            // 温度寄存器地址(浮点型,占2个16位寄存器)
#define REG_HUMI 0x0002            // 湿度寄存器地址(浮点型,占2个16位寄存器)
#define REG_LED_CTRL 0x0004        // LED控制寄存器(1个16位寄存器,0=灭,1=亮)

// Modbus寄存器缓冲区(10个16位寄存器,足够使用)
static uint16_t modbus_regs[10] = {0};

int main() {
    modbus_t *ctx = NULL;
    int sock_fd, ret;
    float temp, humi;
    int aht10_fd = aht10_open();  // 打开AHT10(复用之前的函数)
    
    if (aht10_fd < 0) {
        fprintf(stderr, "AHT10 open failed\n");
        return -1;
    }

    // 1. 初始化Modbus TCP上下文
    ctx = modbus_new_tcp("0.0.0.0", MODBUS_TCP_PORT);  // 监听所有网卡
    if (ctx == NULL) {
        fprintf(stderr, "modbus new tcp failed: %s\n", modbus_strerror(errno));
        close(aht10_fd);
        return -1;
    }

    // 2. 设置从站地址
    modbus_set_slave(ctx, MODBUS_SLAVE_ID);

    // 3. 创建TCP监听套接字
    sock_fd = modbus_tcp_listen(ctx, 1);  // 最大1个连接(工业网关常用)
    if (sock_fd < 0) {
        fprintf(stderr, "modbus tcp listen failed: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        close(aht10_fd);
        return -1;
    }

    printf("Modbus TCP server start: %s:%d\n", "0.0.0.0", MODBUS_TCP_PORT);

    while (1) {
        // 4. 等待客户端连接(阻塞)
        ret = modbus_tcp_accept(ctx, &sock_fd);
        if (ret < 0) {
            fprintf(stderr, "modbus accept failed: %s\n", modbus_strerror(errno));
            continue;
        }
        printf("Client connected\n");

        // 5. 循环处理客户端请求
        while (1) {
            uint8_t req_buf[MODBUS_TCP_MAX_ADU_LENGTH] = {0};
            int req_len;

            // 读取客户端请求
            req_len = modbus_receive(ctx, req_buf, MODBUS_TCP_MAX_ADU_LENGTH);
            if (req_len <= 0) {
                if (req_len == -1) {
                    fprintf(stderr, "modbus receive failed: %s\n", modbus_strerror(errno));
                } else {
                    printf("Client disconnected\n");
                }
                break;
            }

            // 6. 实时更新温湿度到Modbus寄存器(浮点型转2个16位寄存器)
            if (aht10_read(aht10_fd, &temp, &humi) == 0) {
                // 浮点型转字节数组,再拆分到16位寄存器(大端序,工业标准)
                uint8_t temp_bytes[4], humi_bytes[4];
                memcpy(temp_bytes, &temp, 4);
                memcpy(humi_bytes, &humi, 4);

                modbus_regs[REG_TEMP] = (temp_bytes[0] << 8) | temp_bytes[1];
                modbus_regs[REG_TEMP + 1] = (temp_bytes[2] << 8) | temp_bytes[3];
                modbus_regs[REG_HUMI] = (humi_bytes[0] << 8) | humi_bytes[1];
                modbus_regs[REG_HUMI + 1] = (humi_bytes[2] << 8) | humi_bytes[3];

                printf("Update: Temp=%.1f℃, Humi=%.1f%%RH\n", temp, humi);
            }

            // 7. 处理请求(读寄存器、写寄存器)
            ret = modbus_reply(ctx, req_buf, req_len, modbus_regs);
            if (ret < 0) {
                fprintf(stderr, "modbus reply failed: %s\n", modbus_strerror(errno));
                break;
            }

            // 8. 处理LED控制指令(客户端写REG_LED_CTRL寄存器)
            static int last_led_state = -1;
            int current_led_state = modbus_regs[REG_LED_CTRL];
            if (current_led_state != last_led_state) {
                if (current_led_state == 1) {
                    system("echo '1' > /dev/stm32mp1_led");  // LED亮
                    printf("LED ON\n");
                } else {
                    system("echo '0' > /dev/stm32mp1_led");  // LED灭
                    printf("LED OFF\n");
                }
                last_led_state = current_led_state;
            }
        }

        // 关闭客户端连接
        modbus_close(ctx);
    }

    // 资源释放(实际不会执行到)
    modbus_tcp_close_listen_socket(sock_fd);
    modbus_free(ctx);
    close(aht10_fd);
    return 0;
}
(2)交叉编译(链接 libmodbus 库)

bash

arm-linux-gnueabihf-gcc modbus_tcp_server.c aht10_linux.c -o modbus_server \
-static -lmodbus -lm  # -lm:链接数学库(浮点运算可能需要)
(3)上位机验证(Modbus Poll)
  1. 开发板联网,获取 IP(如 192.168.1.100);
  2. 电脑安装 Modbus Poll,配置连接:
    • Connection → TCP/IP → 输入开发板 IP(192.168.1.100),端口 502;
  3. 配置寄存器读取:
    • Protocol → Modbus TCP → 选择 “3: Read Holding Registers”;
    • 起始地址 0,寄存器数量 5,数据类型 “32-bit float, Big-endian”;
  4. 点击 “Connect”,即可看到温湿度数据;
  5. 配置寄存器写入:
    • Protocol → 06: Write Single Register → 地址 4,数值 1 → 点击 “Write”,开发板 LED 亮;数值 0 → LED 灭。
3. 拓展:Modbus TCP 客户端(网关主动上报 PLC)

如果需要网关主动向 PLC(Modbus TCP 服务器)发送数据,可基于libmodbus实现客户端,核心逻辑:

c

// 连接PLC服务器
ctx = modbus_new_tcp("192.168.1.200", 502);  // PLC IP
modbus_set_slave(ctx, 1);
if (modbus_connect(ctx) < 0) { /* 错误处理 */ }

// 向PLC寄存器写入温湿度数据
modbus_write_registers(ctx, 0x0000, 2, &modbus_regs[REG_TEMP]);  // 写入温度
modbus_write_registers(ctx, 0x0002, 2, &modbus_regs[REG_HUMI]);  // 写入湿度

(三)项目部署自动化:Shell 脚本 + Systemd 服务(25 分钟)

实际工作中,部署多台设备时,手动拷贝文件、启动应用效率极低,通过 Shell 脚本批量部署 + Systemd 服务管理,实现 “一键部署、开机自启、异常重启”。

1. 自动化部署 Shell 脚本(deploy.sh)

bash

#!/bin/bash
# 嵌入式Linux项目自动化部署脚本
# 适用:STM32MP157 Linux开发板

# 配置参数
TARGET_IP="192.168.1.100"  # 开发板IP(可批量修改为多个IP)
TARGET_USER="root"
LOCAL_APP_DIR="./bin"       # 本地应用目录
TARGET_APP_DIR="/root/app"  # 开发板应用目录
DRIVER_FILE="led_drv.ko"    # 驱动文件
SERVICE_FILE="modbus-server.service"  # Systemd服务文件

# 1. 检查本地文件是否存在
if [ ! -f "$LOCAL_APP_DIR/modbus_server" ] || [ ! -f "$DRIVER_FILE" ] || [ ! -f "$SERVICE_FILE" ]; then
    echo "错误:本地文件缺失!"
    exit 1
fi

# 2. 登录开发板,创建应用目录
echo "正在连接开发板 $TARGET_IP..."
ssh $TARGET_USER@$TARGET_IP "mkdir -p $TARGET_APP_DIR"

# 3. 上传应用、驱动、服务文件
echo "正在上传文件..."
scp $LOCAL_APP_DIR/modbus_server $TARGET_USER@$TARGET_IP:$TARGET_APP_DIR/
scp $DRIVER_FILE $TARGET_USER@$TARGET_IP:$TARGET_APP_DIR/
scp $SERVICE_FILE $TARGET_USER@$TARGET_IP:/etc/systemd/system/

# 4. 开发板执行部署命令
echo "正在部署..."
ssh $TARGET_USER@$TARGET_IP "
    # 加载驱动
    insmod $TARGET_APP_DIR/$DRIVER_FILE;
    # 设置应用可执行权限
    chmod +x $TARGET_APP_DIR/modbus_server;
    # 重新加载Systemd配置
    systemctl daemon-reload;
    # 设置服务开机自启并启动
    systemctl enable modbus-server.service;
    systemctl start modbus-server.service;
    # 查看服务状态
    systemctl status modbus-server.service;
"

echo "部署完成!"
2. Systemd 服务配置(modbus-server.service)

Systemd 是 Linux 系统的服务管理器,用于管理应用的启动、停止、自启、异常重启,比传统 init 脚本更可靠:

ini

[Unit]
Description=Modbus TCP Server (Industrial Gateway)
After=network.target  # 网络启动后再启动服务
Requires=network.target  # 依赖网络服务

[Service]
Type=simple
User=root
WorkingDirectory=/root/app  # 工作目录
ExecStart=/root/app/modbus_server  # 应用启动命令
Restart=always  # 异常退出时自动重启
RestartSec=3  # 重启间隔3秒
StandardOutput=journal+console  # 日志输出到控制台和系统日志
StandardError=journal+console

[Install]
WantedBy=multi-user.target  # 多用户模式下启动
3. 脚本使用与验证

bash

# 1. 给脚本添加执行权限
chmod +x deploy.sh

# 2. 一键部署(需开发板开启SSH服务)
./deploy.sh

# 3. 验证部署结果
# 本地查看服务状态
ssh root@192.168.1.100 "systemctl status modbus-server.service"
# 查看应用日志
ssh root@192.168.1.100 "journalctl -u modbus-server.service -f"

三、实战项目:工业级 Modbus TCP 网关(30 分钟)

整合第 30 天的三大核心技术,打造 “可量产、高可靠” 的工业级 Modbus TCP 网关,核心功能:

  1. 系统优化:内核裁剪 + 根文件系统精简,RAM 占用≤20MB,Flash 占用≤30MB,启动时间≤10 秒;
  2. 数据采集:AHT10 温湿度采集,1 秒更新一次;
  3. 工业通信:Modbus TCP 服务器,支持上位机读取温湿度、控制 LED;
  4. 云端协同:整合之前的 MQTT 功能,将温湿度数据同步上传阿里云;
  5. 自动化部署:Shell 脚本一键部署,Systemd 服务开机自启、异常重启。

核心验证点

  • 稳定性:连续运行 24 小时,Modbus TCP 连接无断开,数据无丢失;
  • 资源占用:启动后 RAM≤18MB,CPU 占用≤10%;
  • 自动化:开发板上电后自动启动服务,手动杀死应用后 3 秒内自动重启;
  • 工业适配:上位机(Modbus Poll/PLC)可稳定读写数据,响应延迟≤50ms。

四、第三十天必掌握的 3 个核心点

  1. Linux 系统优化:会用 Buildroot 裁剪内核和根文件系统,降低资源占用、优化启动时间,适配嵌入式硬件;
  2. 工业协议实战:掌握 libmodbus 库的使用,能开发 Modbus TCP 服务器 / 客户端,实现工业数据采集与远程控制;
  3. 自动化部署:能编写 Shell 部署脚本,配置 Systemd 服务,实现应用的一键部署、开机自启、异常重启。

总结

第 30 天的核心是 “嵌入式 Linux 工业级落地”—— 系统优化解决了嵌入式资源有限的痛点,Modbus TCP 实战满足了工业通信的刚需,自动化部署提升了项目交付和维护效率,这三项技能是嵌入式 Linux 工程师的 “必备职场技能”。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值