公司动态
Buildroot 定制工控固件:裁剪系统、预装依赖库、精简开机流程
Buildroot 定制工控固件裁剪系统、预装依赖库、精简开机流程买来的开发板自带的系统开个机要 40 秒里面装了一堆桌面浏览器和游戏。工控设备要这个干嘛今天就用 Buildroot 把它裁到只剩骨架。一、Buildroot 简介1.1 什么是 BuildrootBuildroot 是一个轻量级的 Linux 系统构建框架通过菜单配置menuconfig自动完成交叉编译工具链、内核、bootloader、rootfs 的编译最终生成可直接烧录的固件镜像。1.2 Buildroot vs Yocto对比项BuildrootYocto学习曲线低上手快高需要学 BitBake 语法构建速度快单次构建慢但支持增量构建系统体积小适合精简系统可大可小更灵活包管理无包管理整体rootfs支持 RPM/DEB/IPK适合场景工控、嵌入式小设备复杂产品、需要OTA升级工控设备选 Buildroot 的理由系统小、构建快、够用就行。Yocto 的灵活性在固定功能的工控板上反而是累赘。二、Buildroot 目录结构与配置流程2.1 目录结构buildroot/ ├── Makefile # 顶层Makefile一切入口 ├── configs/ # 默认配置文件defconfig ├── package/ # 所有可用软件包定义 ├── output/ # 编译输出自动生成 │ ├── images/ # 最终固件镜像 │ ├── build/ # 编译中间产物 │ ├── host/ # 主机工具链 │ └── target/ # rootfs目录树 ├── board/ # 板级配置设备树、配置文件 ├── dl/ # 下载的源码包缓存 └── fs/ # 文件系统格式定义ext4/jffs2等2.2 配置流程# 1. 选一个默认配置作为起点makelist-defconfigs# 列出所有支持的板子配置makestm32mp15_disco_defconfig# 以STM32MP15开发板为起点# 2. 打开菜单配置makemenuconfig# 3. 配置内核makelinux-menuconfig# 4. 一键编译全自动make# 5. 编译完成后固件在 output/images/lsoutput/images/# sdcard.img u-boot.bin zImage rootfs.ext4 ...三、系统裁剪策略3.1 裁剪原则工控系统裁剪的核心思路是不留任何用不上的东西。每多一个组件就多一份启动时间、一份内存占用、一份攻击面。3.2 menuconfig 裁剪清单Target options目标架构Target Architecture - ARM little endian Target Architecture Variant - cortex-A7 # 根据实际CPU选 Floating point strategy - VFPv4 # 有硬浮点就开Build options构建选项[*] Enable developer macros # 方便调试 [*] Strip target binaries # 去掉调试符号减小体积 Compression method - gzip # rootfs压缩方式Toolchain工具链Toolchain type - External toolchain # 用外部工具链省编译时间 (path/to/arm-linux-gnueabihf-) Toolchain path (arm-linux-gnueabihf) Toolchain prefix [*] Toolchain has C support # 要用QT就开System configuration系统配置(systemd) Init system # 用 systemd如果资源够或 busybox (root) Root password Industrial Device # System hostname /bin/sh # Root shell去掉以下无用组件# 以下全部取消勾选 [ ] X.org X Window System # 不需要图形X11用QT直接走FB [ ] weston / wayland # 除非用Wayland [ ] alsa-utils / pulseaudio # 没音频需求就不装 [ ] gtk3 / enlightenment # 桌面框架 [ ] nginx / lighttpd # 不做Web服务器就不装 [ ] python / python3 # 没用Python就不装省大量空间 [ ] nodejs # 除非你用Node3.3 裁剪效果对比配置rootfs 体积启动时间默认含桌面~120MB~40s裁剪后纯命令行~8MB~8s极限裁剪无网络栈~4MB~4s四、预装依赖库4.1 通过 BR2_PACKAGE 添加软件包Buildroot 内置了大量常用软件包在 menuconfig 中搜索勾选即可Target packages - Libraries - [*] libcurl # HTTP通信 - [*] libmodbus # Modbus协议 - [*] libmosquitto # MQTT客户端 - [*] json-c # JSON解析 - [*] sqlite # 本地数据库 - Networking - [*] dropbear # 轻量SSH服务 - [*] iproute2 # 网络配置工具搜索软件包在 menuconfig 中按/键输入关键词搜索。4.2 添加第三方库自定义包如果 Buildroot 没有内置你要的库可以自己写一个Config.in.mk文件# package/mylib/Config.in config BR2_PACKAGE_MYLIB bool mylib help Custom industrial communication library.# package/mylib/mylib.mk MYLIB_VERSION 1.0.0 MYLIB_SITE $(TOPDIR)/../mylib-src MYLIB_SITE_METHOD local MYLIB_INSTALL_STAGING YES define MYLIB_BUILD_CMDS $(MAKE) CC$(TARGET_CC) -C $(D) endef define MYLIB_INSTALL_TARGET_CMDS $(INSTALL) -D -m 0755 $(D)/libmylib.so $(TARGET_DIR)/usr/lib/ $(INSTALL) -D -m 0644 $(D)/mylib.h $(TARGET_DIR)/usr/include/ endef $(eval $(generic-package))然后在package/Config.in中追加source package/mylib/Config.in重新make menuconfig就能看到你的库了。五、自定义 overlay 目录Overlay 目录可以把你自己的文件直接覆盖到 rootfs 中——配置文件、启动脚本、预编译应用统统放进来。5.1 配置 overlay在 menuconfig 中System configuration - (board/myboard/overlay) Root filesystem overlay directories5.2 overlay 目录结构board/myboard/overlay/ ├── etc/ │ ├── network/ │ │ └── interfaces # 静态IP配置 │ ├── init.d/ │ │ └── S99myapp # 自启动脚本 │ ├── rsyslog.d/ │ │ └── 20-industrial.conf # 日志配置 │ └── hostname ├── usr/ │ └── bin/ │ └── myapp # 预编译应用 └── var/ └── log/编译时 Buildroot 会把这些文件原封不动地拷到 rootfs 对应位置非常直观。六、rootfs 定制6.1 添加自启动脚本方式一init.d 脚本兼容 busybox init 和 systemd#!/bin/sh# /etc/init.d/S99myappcase$1instart)echoStarting myapp.../usr/bin/myapp;;stop)killallmyapp;;restart)$0stopsleep1$0start;;*)echoUsage:$0{start|stop|restart}exit1esacexit0放进 overlay 目录的/etc/init.d/Buildroot 会自动执行。注意S前缀加数字控制启动顺序数字越大越晚执行。方式二systemd service如果用 systemd# /etc/systemd/system/myapp.service [Unit] DescriptionIndustrial Data Collector Afternetwork.target [Service] Typesimple ExecStart/usr/bin/myapp Restartalways RestartSec3 [Install] WantedBymulti-user.target在 rootfs 的 post-build 脚本中执行systemctl enable myapp.service。6.2 网络配置通过 overlay 预置静态 IP# /etc/network/interfaces auto eth0 iface eth0 inet static address 192.168.1.100 netmask 255.255.255.0 gateway 192.168.1.1七、内核配置裁剪用make linux-menuconfig进入内核配置界面裁掉用不到的驱动7.1 必须保留的Device Drivers - GPIO support # GPIO控制 - SPI support # SPI设备 - I2C support # I2C设备 - Serial drivers # 串口 - Network device support # 网卡驱动 - Watchdog Timer # 看门狗 File systems - ext4 # rootfs文件系统 - VFAT # U盘/SD卡FAT格式7.2 可以裁掉的Device Drivers - Graphics support - DRM # 不用DRM可以关但QT EGLFS需要 - Sound card support # 没音频需求 - USB Gadget Support # 不做USB设备模式 - Multimedia support # 没摄像头 File systems - NFS # 不做NFS挂载 - XFS / Btrfs # 工控不需要高级文件系统内核裁剪对启动速度影响显著每去掉一个驱动内核镜像小一点加载快一点。八、精简开机流程8.1 减少启动服务用 systemd 时查看启动耗时systemd-analyze# 总启动时间systemd-analyze blame# 各服务耗时排序systemd-analyze critical-chain# 关键路径分析禁用不需要的服务systemctl disable gettytty1# 不接屏幕可以关systemctl disable systemd-networkd-wait-online# 等网时间太长8.2 优化 init 脚本合并小脚本减少进程创建开销后台启动不阻塞的初始化任务网络配置用静态IP跳过DHCP等待8.3 内核 cmdline 优化在 U-Boot 的 bootargs 中添加quiet # 关闭内核启动日志输出 loglevel3 # 只显示ERR及以上 rootdelay0 # 不等待 rw # 直接可读写挂载九、固件生成与烧录9.1 编译输出编译完成后output/images/目录下会生成文件说明sdcard.img完整SD卡镜像可直接dd烧录zImage/Image内核镜像u-boot.bin/u-boot.imgU-Boot引导rootfs.ext4根文件系统镜像*.dtb设备树二进制9.2 烧录方式# 方式一直接烧录整个SD卡镜像ddifoutput/images/sdcard.imgof/dev/sdbbs4Mstatusprogresssync# 方式二分区烧录先写U-Boot再写内核和rootfsddifu-boot.binof/dev/sdbbs512seek2# 然后用fdisk创建分区把zImage和rootfs.ext4写入对应分区十、Buildroot 编译常见问题排查问题原因解决方案dl/目录下载失败国内网络访问慢配置BR2_DL_DIR指向本地缓存或换国内镜像源编译中途 OOM主机内存不够加 swap 或减少并行度make -j1undefined reference to链接顺序问题检查.mk文件依赖声明rootfs 体积过大没开启 stripmenuconfig 中开启Strip target binaries缺少/dev/节点没用 mdev/udev在 menuconfig 中启用mdev或eudevoverlay 文件没生效路径写错overlay 目录结构要和 rootfs 完全对应Python 程序找不到模块精简过度检查是否选了对应的 Python 包十一、menuconfig 配置清单建议一个典型工控固件的推荐配置# 架构 Target Architecture ARM (EABIhf) Toolchain External (arm-linux-gnueabihf) # Init系统 Init system systemd (资源够) 或 busybox (极致精简) # 必装包 libcurl, libmosquitto, libmodbus, json-c sqlite, dropbear, iproute2, ethtool mtd (如果用NAND Flash) # 文件系统 ext4 (rootfs), vfat (U盘) # 去掉的 X11, wayland, alsa, pulseaudio gtk3, qt5(qt6单独配), python nginx, lighttpdBuildroot 的精髓在于只装你真正需要的东西。每个选项都要问自己一句这个功能工控设备用得上吗用不上就大胆关掉。裁出来的系统又小又快维护起来也省心。