文章目录
1.镜像+根文件系统
一、核心概念对照表
| 概念 | 定义 | 举例 | 类比 |
|---|---|---|---|
| 根文件系统 | Linux 运行时挂载的 / 目录树,是"内容" |
/bin、/etc、/opt/camera |
书的内容 |
| 镜像 | 存储介质的逐字节副本,是一个文件 | sdcard.img、rootfs.img |
书的影印件 |
| 固件 | 固化在芯片里的程序 | 单片机 hex、路由器系统 | 硬件里刻的字 |
| 烧录 | 把镜像写入存储介质 | dd if=xxx.img of=/dev/mmcblk0 |
复印 |
| 量产 | 把原型方案批量复制到多台设备 | 生产线批量烧录 | 批量印刷 |
二、MCU 与 MPU 的本质区别
| 维度 | 单片机(MCU) | 微处理器(MPU,跑 Linux) |
|---|---|---|
| 运行内容 | 只有一个程序 | Bootloader + Kernel + 根文件系统 + 多个服务 |
| 启动流程 | 复位 → 执行 main() |
BootROM → SPL → U-Boot → Kernel → systemd → 你的服务 |
| 量产方式 | 烧录 hex/bin 到 Flash | 制作整机镜像,批量写入 eMMC/SD |
| 用户程序形态 | 就是"整个程序" | 是系统里的一个服务 |
| 差异化 | 一般无 | 每台设备需唯一 token/序列号/MAC |
关键结论:MCU 烧"程序",MPU 烧"系统 + 服务"。
三、Linux 启动与自启动机制
3.1 完整启动链路
芯片复位
↓
BootROM(芯片固化,无法修改)
↓
SPL(二级引导,很小)
↓
U-Boot(大引导,加载内核)
↓
Kernel(加载驱动、挂载根文件系统)
↓
init / systemd(PID=1,总调度器)
↓
systemd 读取所有 .service 文件
↓
camera.service 被触发 → 执行 start_camera.sh
↓
启动 mediamtx / frpc / ffmpeg
3.2 为什么 .service 能自动运行?
- systemd 启动时扫描
/etc/systemd/system/等目录下的.service文件。 - 执行
systemctl enable camera.service时,systemd 在/etc/systemd/system/multi-user.target.wants/下创建一个软链接。 - 开机进入
multi-user.target时,systemd 会启动所有被"想要"(Wanted)的服务。 WantedBy=multi-user.target就是告诉 systemd:"我要跟着多用户模式一起启动"。
本质 :enable = 创建软链接。
3.3 为什么不能用 rc.local?
| 对比项 | rc.local | systemd |
|---|---|---|
| 依赖管理 | 无,靠 sleep 硬等 |
声明 After=、Wants=,自动排序 |
| 崩溃重启 | 无 | Restart=on-failure 自动拉起 |
| 日志 | 需自己重定向 | journalctl 统一管理 |
| 并行启动 | 串行,慢 | 并行,快 |
| 量产可控性 | 弱 | 强 |
结论:rc.local 是玩具,systemd 是产品。
四、你的项目架构回顾
4.1 数据流向
USB摄像头 → FFmpeg(H.264编码) → MediaMTX(本机RTSP) → frpc(内网穿透)
→ 阿里云服务器(frps) → 手机VLC远程拉流
4.2 目录结构(原型阶段)
/home/baiwen/video1/
├── mediamtx # MediaMTX 可执行文件
├── mediamtx.yml # MediaMTX 配置
├── frp_0.71.0_linux_arm64/ # FRP 客户端目录
│ ├── frpc
│ └── frpc.toml
├── start_camera.sh # 开机自启脚本
└── camera.log # 运行日志
4.3 三个关键文件
| 文件 | 作用 | 位置 |
|---|---|---|
start_camera.sh |
启动脚本,负责依次拉起三个服务 | /home/baiwen/video1/ |
camera.service |
systemd 服务定义,实现开机自启 | /etc/systemd/system/ |
frpc.toml |
FRP 客户端配置(含 token) | /home/baiwen/video1/frp_xxx/ |
五、从原型到量产:四个阶段
阶段 1:原型验证(你现在)
做法:手动配置,逐台操作
- 装系统
- 拷贝文件到
/home/baiwen/video1/ - 写
camera.service systemctl enable- 重启验证
特点:能跑通,但不能批量复制。
阶段 2:小批量试产(5~20 台)
做法:SD 卡克隆 + 手动改 token
- 在一台样机上配好所有东西
- 用
dd把 SD 卡做成.img - 每台烧完后,手动 SSH 改
frpc.toml的 token - 验证硬件和软件一致性
bash
# 制作镜像
dd if=/dev/mmcblk0 of=sdcard.img bs=4M
# 烧录到新卡
dd if=sdcard.img of=/dev/mmcblk0 bs=4M
缺点:手动改 token,效率低,易出错。
阶段 3:中批量(100 台以上)
做法:定制镜像 + first-boot 自动化
- 用 Yocto 或 Buildroot 定制精简根文件系统
- 把
mediamtx、frpc、脚本、camera.service直接编入镜像 - 用厂商烧录工具(如 RKDevTool、uuu)批量烧录 eMMC
- 首次启动运行
first-boot.service,自动个性化
first-boot 脚本要做的事:
bash
#!/bin/bash
# 1. 生成唯一 token
TOKEN=$(openssl rand -hex 16)
# 2. 生成唯一序列号(用 MAC 地址)
SERIAL=$(cat /sys/class/net/eth0/address | tr -d ':')
# 3. 从模板生成配置文件
sed "s/__TOKEN__/$TOKEN/" /opt/camera/frpc.toml.template > /etc/frp/frpc.toml
# 4. 设置唯一主机名
echo "camera-$SERIAL" > /etc/hostname
# 5. 自我禁用,只跑一次
systemctl disable first-boot.service
阶段 4:正式产品
做法:CI/CD + OTA 升级
- Yocto/Buildroot 做完整构建流水线(代码提交 → 自动编译 → 生成镜像)
- 镜像里预置:
- 应用(打包成
.deb或放到/opt/) - systemd 服务
- RAUC / SWUpdate 做 OTA 升级框架
- A/B 分区方案(升级失败可回滚)
- 应用(打包成
- 生产线用夹具 + 自动化工具烧录,写入序列号、MAC、密钥
- 出厂后通过 OTA 推送更新
六、量产镜像里应该装什么?
6.1 完整交付包结构
你的应用包/
├── opt/camera/ # 应用目录
│ ├── mediamtx # 可执行文件
│ ├── mediamtx.yml # 配置
│ ├── frpc # FRP 客户端
│ ├── frpc.toml.template # 配置模板(token 留空,首启时填)
│ └── start_camera.sh # 启动脚本
├── etc/systemd/system/
│ ├── camera.service # 服务定义
│ └── first-boot.service # 首启个性化服务
└── etc/first-boot.d/
└── 01-personalize.sh # 个性化脚本
6.2 关键点
| 项目 | 原型阶段 | 量产阶段 |
|---|---|---|
| token | 硬编码在 frpc.toml | 用模板 + 首启生成 |
| 主机名 | 手动设置 | 用 MAC 地址自动生成 |
| 服务启动 | 手动 systemctl start |
编入镜像,开机自动 |
| 升级方式 | 手动 SSH 替换 | OTA 推送 |
七、打包方式对比
| 方式 | 适合场景 | 做法 |
|---|---|---|
| 直接拷贝到 rootfs | 自己维护镜像 | 放进 Yocto/Buildroot 的 recipes 或 overlay |
打成 .deb 包 |
Debian/Ubuntu | dpkg-deb --build 生成,安装自动放好服务 |
| Docker 容器 | 应用隔离 | 应用做成镜像,宿主 systemd 拉起容器 |
| 只读分区 | 防篡改 | 根文件系统只读,应用分区单独可写 |
八、镜像 vs 根文件系统:核心区别
| 维度 | 根文件系统 | 镜像 |
|---|---|---|
| 本质 | 目录树(内容) | 文件(副本) |
| 运行时 | 是"活"的,被挂载使用 | 是"死"的,只能被读写 |
| 包含关系 | 是镜像的一部分 | 可以包含根文件系统 |
| 路径 | / |
xxx.img |
| 制作方式 | 用 cp、dpkg 填充 |
用 dd、mkfs、mksquashfs 生成 |
| 使用方式 | 挂载后直接访问 | 用 dd 写入存储介质 |
| 类比 | 书的内容 | 书的影印件 |
一句话 :根文件系统是 Linux 运行时看到的 /;镜像是把它打包成的 .img 文件。
九、术语速查表
| 术语 | 含义 | 类比 |
|---|---|---|
| 镜像 (Image) | 存储介质的逐字节副本 | 书的影印件 |
| 根文件系统 (rootfs) | Linux 运行时的 / 目录树 |
书的内容 |
| 固件 (Firmware) | 固化在芯片里的程序 | 硬件里刻的字 |
| Bootloader | 启动引导程序(U-Boot) | 电脑的 BIOS |
| Kernel | Linux 内核 | 操作系统的心脏 |
| systemd | Linux 的总调度器(PID=1) | 工厂的调度中心 |
| Service | systemd 管理的服务单元 | 工厂里的一条产线 |
| 烧录 | 把镜像写入存储介质 | 复印 |
| 量产 | 批量复制到多台设备 | 批量印刷 |
| OTA | 空中升级 | 手机系统更新 |
| A/B 分区 | 双分区互为备份,升级失败可回滚 | 双系统启动 |
| first-boot | 首次启动时运行的个性化脚本 | 新手机开机设置 |
十、给你的下一步建议
当前状态:原型验证完成 ✅
短期目标(如果你想做几台设备自用):
- 在一台样机上配好所有东西
- 用
dd做成.img - 每台烧完后手动改 token
- 验证一致性
中期目标(如果想做小批量产品):
- 学 Yocto 或 Buildroot,做定制镜像
- 写
first-boot.sh做自动化个性化 - 用厂商烧录工具批量写入
长期目标(如果要做正式产品):
- 引入 OTA 升级框架
- A/B 分区,支持失败回滚
- 云端设备管理
十一、一句话总结整个项目
你做的不是"烧一个程序",而是"部署一个系统"。
镜像 是打包方式,根文件系统 是运行内容,systemd 服务 是启动机制,first-boot 是个性化方案,OTA是升级方案。
这五点就是嵌入式 Linux 产品化的全部骨架。