【Linux】基于busybox移植rootfs根文件系统

1. 前言

我们所熟悉的Linux主要由部分组成:ubootLinux Kernelrootfs(根文件系统)。uboot启动后会加载Linux Kernel,然后Kernel再来挂载rootfs文件系统,进入文件系统后,我们才可以运行我们的应用程序,对不同的设备进行操作。本篇文章主要是介绍通过busybox如何移植制作rootfs最小文件系统

2. 下载Busybox

Busybox官网下载地址:https://busybox.net/
在这里插入图片描述
选择最新的固件:busybox-1.35.0.tar.bz2
在这里插入图片描述

3. 编译Busybox

  • 将下载好的Busybox发送到ubuntu中,并且解压如下:
    tar -jxvf busybox-1.35.0.tar.bz2
    在这里插入图片描述
  • 在编译前需要先在系统声明ARCHCROSS_COMPILE:(NOTE:需要根据硬件平台使用的交叉工具链来配置)
    export ARCH=arm
    export CROSS_COMPILE=arm-none-linux-gnueabihf-
    export PATH=$PATH:/opt/ToolChain/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/bin
    
    在这里插入图片描述
  • 执行make menuconfig,不做任何修改保存并退出。
    在这里插入图片描述
  • 编译busybox
    make -j4
    make install CONFIG_PREFIX=/home/benjamin/nfs_rootfs
    COFIG_PREFIX 指定编译结果的存放目录,我这里是存放在/home/benjamin/nfs_rootfs
    编译完成截图如下:
    在这里插入图片描述
    成功安装到指定的路径如下:
    在这里插入图片描述

4. 向rootfs根文件系统添加lib库

Linux在运行应用程序时需要一些lib库,复制工具链内的lib库文件。

  • nfs_rootfs文件夹下创建lib文件夹,并且拷贝如下:(-d表示:如果原来是链接文件,仍保留链接关系)
    cp -d /opt/ToolChain/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/libc/lib/*.so* ./lib
    在这里插入图片描述
  • nfs_rootfs文件夹下创建usr/lib文件夹,并且拷贝如下:(-d表示:如果原来是链接文件,仍保留链接关系)
    cp -d /opt/ToolChain/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/libc/usr/lib/*so* ./usr/lib/
    cp -d /opt/ToolChain/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/arm-none-linux-gnueabihf/libc/usr/lib/*.a ./usr/lib/
    在这里插入图片描述
  • 创建其它文件夹
    在根文件系统中创建其他文件夹,如下:
    mkdir dev proc mnt sys tmp root
    在这里插入图片描述

5. 根文件系统初步测试

为了方便测试前面创建好的根文件系统rootfs,测试的方法就是使用NFS挂载。在uboot中我们需要设置bootargs和bootcmd,具体参数如下:
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs ip=dhcp nfsroot=192.168.31.218:/home/benjamin/nfs_rootfs,v3,tcp'
setenv bootcmd 'tftp 0x80800000 zImage; tftp 0x83000000 imx6ull-benjamin-emmc.dtb; bootz 0x80800000 - 0x83000000'
测试结果如下:

[    3.003433] SMSC LAN8710/LAN8720 20b4000.ethernet-1:01: attached PHY driver [SMSC LAN8710/LAN8720] (mii_bus:phy_addr=20b4000.ethernet-1:01, irq=POLL)
[    3.025336] fec 2188000.ethernet eth1: Unable to connect to phy
[    3.033300] IP-Config: Failed to open eth1
[    5.123679] fec 20b4000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
[    5.132947] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[    5.163149] Sending DHCP requests ., OK
[    5.207002] IP-Config: Got DHCP answer from 192.168.31.1, my address is 192.168.31.178
[    5.215583] IP-Config: Complete:
[    5.219184]      device=eth0, hwaddr=00:01:3f:2d:3e:4d, ipaddr=192.168.31.178, mask=255.255.255.0, gw=192.168.31.1
[    5.229596]      host=MiWiFi-R4A-srv, domain=, nis-domain=(none)
[    5.235824]      bootserver=192.168.31.1, rootserver=192.168.31.218, rootpath=
[    5.235841]      nameserver0=192.168.31.1
[    5.247709] cfg80211: Loading compiled-in X.509 certificates for regulatory database
[    5.259240] cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
[    5.266261] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
[    5.275278] ALSA device list:
[    5.278270]   #0: wm8960-audio
[    5.282962] platform regulatory.0: Falling back to sysfs fallback for: regulatory.db
[    5.393641] VFS: Mounted root (nfs filesystem) readonly on device 0:16.
[    5.403468] devtmpfs: mounted
[    5.410154] Freeing unused kernel memory: 1024K
[    5.433119] Run /sbin/init as init process

can't run '/etc/init.d/rcS': No such file or directory

Please press Enter to activate this console. 
/ # 
/ # ls
bin      lib      mnt      root     sys      usr
dev      linuxrc  proc     sbin     tmp
/ # 

由上面的打印log可以看出ls命令工作正常!说明rootfs根文件系统基本工作正常,但是进入根文件系统时提示了一个错误:
can't run '/etc/init.d/rcS': No such file or directory
在这里插入图片描述
虽然到这里rootfs已经可以工作,但是还时缺省其它文件,需要我们进一步完善。

6. 完善rootfs根文件系统

  • 创建/etc/init.d/rcS 文件
    rcS 是个 shell 脚本,Linux 内核启动以后需要启动一些服务,而 rcS 就是规定启动哪些文件的脚本文件。在 rootfs 中创建/etc/init.d/rcS 文件,然后在 rcS 中输入如下所示内容:(NOTE:一定要给执行权限,添加执行权限命令如:chmod 777 /etc/init.d/rcS)
    #!/bin/sh
    
    PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
    LD_LIBRARY_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 -s
    
  • 创建/etc/fstab 文件
    在 rootfs中创建/etc/fstab 文件,fstab在Linux开机以后自动配置哪些需要自动挂载的分区,具体输入如下:
    #<file system> <mount point> <type> <options> <dump> <pass>
    proc           /proc         proc   defaults  0      0
    tmpfs          /tmp          tmpfs  defaults  0      0
    sysfs          /sys          sysfs  defaults  0      0
    
  • 创建/etc/inittab 文件
    inittab 的详细内容可以参考 busybox 下的文件 examples/inittab。init 程序会读取/etc/inittab这个文件,inittab 由若干条指令组成。/etc/inittab文件具体输入如下:
    # /etc/inittab
    ::sysinit:/etc/init.d/rcS
    console::askfirst:-/bin/sh
    ::restart:/sbin/init
    ::ctrlaltdel:/sbin/reboot
    ::shutdown:/bin/umount -a -r
    ::shutdown:/sbin/swapoff -a
    
    第 2 行:系统启动以后运行/etc/init.d/rcS 这个脚本文件。
    第 3 行:将 console 作为控制台终端,也就是 ttymxc0。
    第 4 行:重启的话运行/sbin/init。
    第 5 行:按下 ctrl+alt+del 组合键的话就运行/sbin/reboot,看来 ctrl+alt+del 组合键用于重启系统。
    第 6 行:关机的时候执行/bin/umount,也就是卸载各个文件系统。
    第 7 行:关机的时候执行/sbin/swapoff,也就是关闭交换分区。

7. 根文件系统最终测试

经过以上的完善之后,重新通过NFS挂载文件系统,没有任何错误,具体Log如下:

[    5.044138] fec 20b4000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
[    5.073836] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[    5.103376] Sending DHCP requests .., OK
[    8.227482] IP-Config: Got DHCP answer from 192.168.31.1, my address is 192.168.31.178
[    8.236830] IP-Config: Complete:
[    8.240100]      device=eth0, hwaddr=00:01:3f:2d:3e:4d, ipaddr=192.168.31.178, mask=255.255.255.0, gw=192.168.31.1
[    8.250570]      host=MiWiFi-R4A-srv, domain=, nis-domain=(none)
[    8.256886]      bootserver=192.168.31.1, rootserver=192.168.31.218, rootpath=
[    8.256903]      nameserver0=192.168.31.1
[    8.268861] cfg80211: Loading compiled-in X.509 certificates for regulatory database
[    8.280355] cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
[    8.287374] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
[    8.296389] ALSA device list:
[    8.299380]   #0: wm8960-audio
[    8.303418] platform regulatory.0: Falling back to sysfs fallback for: regulatory.db
[    8.403914] VFS: Mounted root (nfs filesystem) readonly on device 0:16.
[    8.413576] devtmpfs: mounted
[    8.419314] Freeing unused kernel memory: 1024K
[    8.443757] Run /sbin/init as init process

Please press Enter to activate this console. 
/ # 
/ # 
/ # 
/ # ls
bin      etc      linuxrc  proc     sbin     tmp
dev      lib      mnt      root     sys      usr
/ # 

在这里插入图片描述

8. 移植过程错误汇总


问题一

[    6.173526] Run /sbin/init as init process
[    6.412362] request_module: kmod_concurrent_max (0) close to 0 (max_modprobes: 50), for module binfmt-464c, throttling...
[   11.443066] request_module: modprobe binfmt-464c cannot be processed, kmod busy with 50 threads for more than 5 seconds now
[   11.480035] Starting init: /sbin/init exists but couldn't execute it (error -8)

问题分析:
Kernel在启动/sbin/init时出现的错误,查看执行文件,它是从/bin/busybox软链接过来。
在这里插入图片描述
查看发现/bin/busybox文件是64bit x86-64架构的,所以可以知道应该移植busybox时没有修改交叉编译工具。
在这里插入图片描述
解决办法:
编译前先指定架构和编译工具:
在这里插入图片描述
再次查看/bin/busybox文件:
在这里插入图片描述


问题二

/etc/init.d/rcS: line 12: can't create /proc/sys/kernel/hotplug: nonexistent directory

问题分析:
根据打印Log可以知道,Linux Kernel还没有hotplug功能,需要在Kernel里面进行添加。

解决办法:
配置CONFIG_UEVENT_HELPER=y,位置如下:

  │   Location:-> Device Drivers 
  │       -> Generic Driver Options 
  │ (2)     -> Support for uevent helper (UEVENT_HELPER [=y])

在这里插入图片描述


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会尽力回答你的问题。首先,busybox是一个非常小巧的程序集合,它集成了许多常用的Linux工具,可以用来替代传统的Linux命令行工具,从而使得系统的启动时间更快、占用的空间更小。基于busybox的根文件系统可以使得系统更加轻量级,并且可以方便地定制。下面是实现基于busybox的根文件系统的步骤: 1. 下载busybox源代码,并编译生成busybox可执行文件。你可以从busybox的官网上下载源代码,然后使用make命令进行编译。 2. 创建一个新的目录作为根文件系统的挂载点。你可以使用mkdir命令创建一个空目录。 3. 将busybox可执行文件复制到根文件系统目录中。你可以使用cp命令将busybox可执行文件复制到根文件系统目录中。 4. 在根文件系统目录中创建必要的目录和文件。根据你的需求,你可以使用mkdir和touch命令创建必要的目录和文件。 5. 创建一个init脚本来启动系统。init脚本是系统的启动脚本,用来初始化系统并启动其他进程。你可以使用vi或者nano等编辑器创建init脚本。 6. 将根文件系统目录打包成一个镜像文件。你可以使用tar命令将根文件系统目录打包成一个tar包,然后使用mkfs命令将tar包转换成一个镜像文件。 7. 将镜像文件烧录到SD卡或者其他存储介质中。你可以使用dd命令将镜像文件写入到SD卡或者其他存储介质中。 以上就是基于busybox的根文件系统制作的基本步骤,你可以根据你的需求进行定制和修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值