正点原子IMX6ULL移植Linux(5)---从Busybox到可启动:根文件系统构建实战与排错

张开发
2026/5/26 21:17:52 15 分钟阅读
正点原子IMX6ULL移植Linux(5)---从Busybox到可启动:根文件系统构建实战与排错
1. Busybox配置与编译实战第一次接触Busybox时我被它瑞士军刀般的特性惊艳到了。这个不足2MB的二进制文件竟然能替代上百个常用Linux命令。在IMX6ULL平台上构建根文件系统Busybox绝对是核心组件。下面分享我在正点原子开发板上踩坑总结的完整流程。先到官网下载最新稳定版当前是1.37.0解压后重点修改两个地方首先是顶层Makefile的交叉编译工具链配置。我的开发环境用的是Linaro 7.5.0版本路径设置如下ARCH ? arm CROSS_COMPILE ? /usr/local/arm/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-中文支持是个大坑很多教程都没提到需要修改两个关键文件libbb/printable_string.c中要把if (c )改为if (c c ! \t)libbb/unicode.c中注释掉*d (c c 0x7f) ? c : ?这行配置阶段建议先用make defconfig生成基础配置再用make menuconfig微调。有几个关键选项新手容易忽略静态编译Settings → Build static binary建议关闭Coreutils → sync要启用否则文件系统可能损坏Linux System Utilities → mdev要开启这是设备管理的关键编译时可能会遇到两个典型错误sha1_process_block64_shaNI未定义编辑libbb/hash_md5_sha.c把所有带shaNI的代码段注释掉IFLA_CAN_TERMINATION未定义在include/linux/if_link.h中添加宏定义#define IFLA_CAN_TERMINATION 132. 根文件系统骨架搭建编译完成后执行make install CONFIG_PREFIX/path/to/rootfs这时会生成最基本的文件结构。但要想系统能真正运行还需要补充大量内容。我的经验是按照这个顺序完善库文件补充是最容易出问题的环节。首先把交叉编译器的库文件复制到rootfs/lib下cp /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/*.so* /rootfs/lib -d特别注意ld-linux-armhf.so.3这个动态链接器需要单独处理rm /rootfs/lib/ld-linux-armhf.so.3 # 先删除无效软链接 cp /usr/local/arm/gcc.../libc/lib/ld-linux-armhf.so.3 /rootfs/lib/关键目录创建也不能少mkdir -p dev proc mnt sys tmp root etc/init.d usr/lib测试时发现一个隐藏坑点如果直接复制所有.so文件可能会包含x86架构的库。建议用file命令检查关键库的架构file libc.so.6 # 应该显示ARM架构3. NFS挂载的魔鬼细节用NFS挂载根文件系统调试时bootargs参数配置让我折腾了整整两天。正点原子教程里的配置setenv bootargs consolettymxc0,115200 root/dev/nfs nfsroot192.168.1.250:/nfs/rootfs,prototcp rw ip192.168.1.251...在实际测试中我发现三个关键点必须加上v3参数明确使用NFSv3协议静态IP配置容易出问题建议先用DHCP内核要开启DHCP支持Networking options → IP: DHCP support最终可用的配置是这样的setenv bootargs consolettymxc0,115200 root/dev/nfs nfsroot10.42.0.1:/nfs/rootfs,tcp,v3 rw ipdhcp如果遇到挂载失败建议按这个顺序排查检查NFS服务器是否正常运行sudo exportfs -v确认内核配置CONFIG_ROOT_NFSy测试基础网络连通性ping 10.42.0.1在服务器上手动挂载测试mount -t nfs localhost:/nfs/rootfs /mnt4. 关键启动脚本剖析系统启动时最先读取的是/etc/inittab这个文件相当于系统的启动蓝图。Busybox版的inittab有自己独特的语法::sysinit:/etc/init.d/rcS console::askfirst:-/bin/sh ::restart:/sbin/init ::ctrlaltdel:/sbin/rebootrcS脚本是系统初始化的核心有几个易错点PATH要包含常用命令路径必须导出LD_LIBRARY_PATHmdev设备管理不能少#!/bin/sh PATH/sbin:/bin:/usr/sbin:/usr/bin:$PATH LD_LIBRARY_PATH/lib:/usr/lib export PATH LD_LIBRARY_PATH mount -a mkdir /dev/pts mount -t devpts devpts /dev/pts echo /sbin/mdev /proc/sys/kernel/hotplug mdev -sfstab文件决定了自动挂载项典型配置如下proc /proc proc defaults 0 0 tmpfs /tmp tmpfs defaults 0 0 sysfs /sys sysfs defaults 0 0遇到过最诡异的问题是系统启动后网络接口不工作后来发现是rcS里缺少网络初始化。建议在脚本最后加上ifup eth0 # 或者你的网卡名称5. 排错经验与性能优化系统能启动只是第一步真正稳定运行还需要更多调优。分享几个实战技巧日志查看当系统启动卡住时在bootargs加上loglevel8可以显示详细内核信息。常见问题有库文件版本不匹配error while loading shared libraries脚本权限问题Permission denied挂载失败mount: mounting /dev on /dev failed性能优化在menuconfig中关闭Debug选项Settings → Build Options使用-Os优化级别而非-O2移除不需要的命令如awk/sed等存储优化特别重要# 压缩rootfs find . | cpio -o -H newc | gzip ../rootfs.cpio.gz # 检查各目录大小 du -h --max-depth1遇到最头疼的问题是随机性启动失败后来发现是mdev设备初始化时序问题。解决方案是在rcS中加入延时sleep 1 # 等待设备节点创建完成 mdev -s6. 进阶配置技巧当基础系统跑通后可以考虑添加这些实用功能用户管理创建/etc/passwd文件添加root用户配置/etc/shadow设置密码修改inittab中的启动shell为/bin/login网络配置# /etc/network/interfaces auto eth0 iface eth0 inet dhcp开机自启服务# /etc/init.d/S99myapp #!/bin/sh /myapp/bin/start 调试技巧使用strace跟踪系统调用通过gdbserver远程调试添加-v参数启用详细日志有个特别实用的技巧是在rcS中添加这些调试命令# 打印启动时间 echo Init done at: $(date) /tmp/boottime.log # 生成系统信息报告 busybox free /tmp/meminfo

更多文章