4. 开发环境搭建:交叉编译工具链安装、远程开发配置(SSH/VSCode)、边缘设备系统烧录与初始化、Docker环境部署

说实话,很多做AI算法的朋友,一碰到边缘设备就头疼。为什么?因为开发环境太碎了。你想想看,在服务器上跑模型,装个conda环境就完事了。但在边缘设备上,你得搞定交叉编译、系统烧录、远程调试……每一步都可能踩坑。

我个人习惯,先把环境分成四块来搞:交叉编译工具链远程开发配置设备系统烧录Docker部署。这四块搞定了,后面的大模型部署才能顺风顺水。

核心思路:边缘设备资源有限,我们必须在宿主机(通常是x86架构的PC)上编译好二进制,再传到ARM架构的边缘设备上运行。这就是交叉编译的由来。

边缘计算开发环境搭建流程 宿主机(x86) 交叉编译工具链 VSCode + SSH Remote Docker 构建环境 交叉编译 编译产物 .so / .bin / Docker镜像 模型文件(.onnx/.tflite) scp/rsync 边缘设备(ARM) 系统烧录(SD卡/eMMC) Docker 运行时 模型推理服务 SSH远程连接 → 代码同步 → 远程调试 → 部署运行 ⚠ 关键点 架构匹配(aarch64 vs armv7) 💡 技巧 使用Docker统一开发环境 🔧 工具 VSCode Remote + SSH

4.1 交叉编译工具链安装

交叉编译,说白了就是在你的x86电脑上,编译出能在ARM芯片上跑的程序。我刚开始搞这个的时候,以为装个gcc就完事了,结果编译出来的程序在板子上直接报错——段错误。后来才发现,工具链版本和glibc版本必须匹配。

这里我以架构为例,讲一下标准流程:

# 下载Linaro官方工具链(推荐gcc-linaro-7.5.0)
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz

# 解压到指定目录
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz -C /opt/

# 配置环境变量(建议写入~/.bashrc)
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64

# 验证安装
aarch64-linux-gnu-gcc --version

⚠ 我曾经踩过的坑:工具链版本太高,导致编译出来的程序在旧版内核上跑不起来。比如用gcc-10编译的程序,在Linux 4.9内核的设备上可能因为glibc版本不兼容而报错。建议先查一下设备的内核版本,再选工具链。

我个人习惯,会在宿主机上装多个版本的工具链,用环境变量切换:

# 在~/.bashrc中定义别名
alias use-gcc7='export PATH=/opt/gcc-linaro-7.5.0/bin:$PATH'
alias use-gcc9='export PATH=/opt/gcc-linaro-9.2.0/bin:$PATH'

4.2 远程开发配置(SSH/VSCode)

你想想看,每次改代码都要手动scp到板子上,再ssh上去运行,多麻烦。VSCode的Remote-SSH插件就是干这个的——让你在本地写代码,远程编译调试。

配置步骤其实很简单:

  1. 宿主机上生成SSH密钥(免密登录必备)
  2. 把公钥拷贝到边缘设备
  3. VSCode安装Remote-SSH插件
  4. 配置SSH config文件
# 1. 生成密钥(宿主机上执行)
ssh-keygen -t rsa -b 4096

# 2. 拷贝公钥到边缘设备
ssh-copy-id user@192.168.1.100

# 3. VSCode SSH Config (~/.ssh/config)
Host edge-device
    HostName 192.168.1.100
    User root
    Port 22
    IdentityFile ~/.ssh/id_rsa
    ForwardAgent yes

💡 小技巧:如果边缘设备没有显示器,可以用串口先配置好网络和SSH服务。我一般用screen命令连串口:screen /dev/ttyUSB0 115200

配置好之后,在VSCode里按F1,输入"Remote-SSH: Connect to Host",选你的设备。嗯,这时候你会发现,VSCode的终端直接连到了板子上,文件浏览器里看到的是板子的文件系统。爽不爽?

4.3 边缘设备系统烧录与初始化

这一步,说白了就是把操作系统写到SD卡或eMMC里。不同设备烧录方式不一样,但核心思路是一样的:下载镜像 → 写入存储介质 → 启动配置

以树莓派4B为例(很多边缘设备都类似):

# 1. 下载系统镜像(Ubuntu Server 22.04 LTS for ARM64)
wget https://cdimage.ubuntu.com/releases/22.04/release/ubuntu-22.04.3-preinstalled-server-arm64+raspi.img.xz

# 2. 解压并写入SD卡(注意:/dev/sdb是你的SD卡设备)
xzcat ubuntu-22.04.3-preinstalled-server-arm64+raspi.img.xz | sudo dd of=/dev/sdb bs=4M status=progress

# 3. 挂载并配置(启用SSH、设置WiFi)
# 挂载boot分区
sudo mount /dev/sdb1 /mnt
# 启用SSH(创建空文件)
sudo touch /mnt/ssh
# 配置WiFi(可选)
sudo nano /mnt/wpa_supplicant.conf

初始化清单(必做项):

  • ✅ 修改默认密码(passwd命令)
  • ✅ 更新系统(apt update && apt upgrade)
  • ✅ 安装必要工具(git, vim, htop, net-tools)
  • ✅ 配置静态IP(避免每次重启IP变化)
  • ✅ 关闭不必要的服务(蓝牙、Avahi等)
  • ✅ 设置swap分区(内存小的设备尤其重要)

我记得有一次,给客户部署设备,忘了配静态IP。结果设备重启后IP变了,远程连不上,只能跑现场去接显示器。从那以后,我每次烧录完系统,第一件事就是配静态IP。

# 配置静态IP(Ubuntu 22.04使用netplan)
sudo nano /etc/netplan/01-netcfg.yaml

# 示例配置
network:
  version: 2
  ethernets:
    eth0:
      dhcp4: no
      addresses:
        - 192.168.1.100/24
      gateway4: 192.168.1.1
      nameservers:
        addresses: [8.8.8.8, 114.114.114.114]

4.4 Docker环境部署

为什么要在边缘设备上用Docker?说白了,就是为了环境一致性。你在宿主机上编译好的环境,打包成镜像,传到板子上直接跑,省去了一堆依赖问题。

我建议在宿主机上构建镜像,然后传到边缘设备上运行。这样可以利用x86的算力做编译,ARM设备只负责运行。

# 宿主机上:构建ARM64架构的Docker镜像
# 先安装buildx插件(用于多架构构建)
docker buildx create --name mybuilder --use
docker buildx inspect --bootstrap

# 编写Dockerfile(示例)
FROM arm64v8/ubuntu:22.04
RUN apt-get update && apt-get install -y \
    python3 python3-pip \
    libopenblas-dev \
    libopencv-dev
COPY ./model_server /app/
WORKDIR /app
CMD ["python3", "server.py"]

# 构建并推送
docker buildx build --platform linux/arm64 -t mymodel:latest --load .

# 保存镜像为tar文件
docker save mymodel:latest -o mymodel.tar

# 传到边缘设备
scp mymodel.tar root@192.168.1.100:/root/

# 边缘设备上:加载并运行
docker load -i mymodel.tar
docker run -d --restart=always --name model-server -p 8080:8080 mymodel:latest

⚠ 注意:边缘设备的存储空间通常很小(8GB-32GB),Docker镜像要尽量精简。我一般用alpine作为基础镜像,能省掉一半以上的空间。另外,记得定期清理无用的镜像和容器:docker system prune -a

还有一个技巧——使用Docker Compose管理多容器。比如你的大模型服务需要同时跑推理引擎、API网关、日志收集,用docker-compose.yml一键启动,省心多了。

# docker-compose.yml 示例
version: '3'
services:
  inference:
    image: mymodel:latest
    ports:
      - "8080:8080"
    volumes:
      - ./models:/app/models
    restart: always
  monitor:
    image: prom/node-exporter:latest
    ports:
      - "9100:9100"
    restart: always

嗯,到这里,开发环境就搭好了。你可以在宿主机上写代码、交叉编译,通过SSH/VSCode远程调试,用Docker打包部署。这套流程我用了好几年,从NVIDIA Jetson到RK3588,从树莓派到算能盒子,基本都能套用。

💡 最后一个小建议:把环境搭建的步骤写成脚本,一键执行。我每次拿到新设备,跑一遍./setup_env.sh,半小时就能把环境配好。别小看这个,项目多了你就知道有多香了。

专注资料整理