使用BusyBox编译根文件系统(zdyz)

1.使用BusyBox编译根文件系统

1.BusyBox 可以在其官网下载到,官网地址为: https://busybox.net/ ,Download Source 1.29.0版本。
mkdir rootfs
//创建好的 rootfs 子目录就用来存放我们的根文件系统了。
tar -vxjf busybox-1.29.0.tar.bz2
//解压busybox至任意目录

打开 busybox 的顶层 Makefile,添加 ARCH 和 CROSS_COMPILE的值:

164 CROSS_COMPILE ?= /usr/local/arm/gcc-linaro-4.9.4-2017.01-
x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
......
190 ARCH ?= arm

2busybox 中文字符支持

打开文件 busybox-1.29.0/libbb/printable_string.c,找到函数 printable_string

 打开文件 busybox-1.29.0/libbb/unicode.c

3.配置 busybox 

①、defconfig,缺省配置,也就是默认配置选项。
②、allyesconfig,全选配置,也就是选中 busybox 的所有功能。

③、allnoconfig,最小配置。

一般使用make defconfig ,然后打开make menuconfig,

a. Settings -> Build static binary (no shared libs)  注意不要选中!
选项“Build static binary (no shared libs)”用来决定是静态编译 busybox 还是动态编译,静
态编译的话就不需要库文件,但是编译出来的库会很大。动态编译的话要求根文件系统中有库
文件,但是编译出来的 busybox 会小很多。这里我们不能采用静态编译!因为采用静态编译的
话 DNS 会出问题!无法进行域名解析。

b. Settings -> vi-style line editing commands ,选中这个

c. Linux Module Utilities -> Simplified modutils  ,取消勾选。

d.Linux System Utilities -> mdev (16 kb),确保下面的全部选中。

d.Settings ->Support Unicode (选中)-> Check $LC_ALL, $LC_CTYPE and $LANG environment variables(选中)

4、编译 busybox

配置好 busybox 以后就可以编译了,我们可以指定编译结果的存放目录,我们肯定要将编
译结果存放到前面创建的 rootfs 目录中,输入如下命令:

make
make install CONFIG_PREFIX=/home/linux/nfs/rootfs
COFIG_PREFIX 指 定 编 译 结 果 的 存 放 目 录 。编译完成以后会在 busybox 的所有工具和文件就会被安装到 rootfs 目录中。
此时:rootfs 目录下有 bin、sbin 和 usr 这三个目录,以及 linuxrc 这个文
init 进程最后会查找用户空间的 init 程序,找到以后就会运行这个用户空间的 init 程序,从而切换到用户态。如果 bootargs 设置 init=/linuxrc,那么 linuxrc 就是可以作为用户空间的 init 程序,所以用户态空间的 init 程序是 busybox 来生成的。
busybox 的工作就完成了,但是此时的根文件系统还不能使用。

 5.向根文件系统添加 lib

a.向 rootfs 的“/lib”目录添加库文件

在 rootfs 中创建一个名为“lib”的文件夹,命令如下:

mkdir lib

lib 库文件从交叉编译器中获取,前面搭建交叉编译环境的时候将交叉编译器存放到了“/usr/local/arm/”目录中。

cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib

cp *so* *.a /home/linux/nfs/rootfs/lib/ -d
#后面的“-d”表示拷贝符号链接

但是其中ld-linux-armhf.so.3是软链接,只有24kb,因此需要删除它,然后复制本尊。

rm ld-linux-armhf.so.3
cd  /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
cp ld-linux-armhf.so.3 /home/linux/nfs/rootfs/lib/


cp *so* *.a /home/linux/nfs/rootfs/lib/ -d

b.rootfs 的“usr/lib”目录添加库文件

在 rootfs 的 usr 目录下创建一个名为 lib 的目录,将如下目录中的库文件拷贝到 rootfs/usr/lib
目录下:

cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib

 *so* *.a /home/linux/nfs/rootfs/usr/lib/ -d

c.创建其他文件夹

在根文件系统中创建其他文件夹,如 devprocmntsystmp root

 6.根文件系统的初步测试

nfs挂载

uboot 里面的 bootargs 环境变量会设置“root”的值,所以我们将 root 的值改为 NFS 挂载即可。在 Linux 内核源码里面有相应的文档讲解如何设置,文档为 Documentation/filesystems/nfs/nfsroot.txt,格式如下:

root=/dev/nfs nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>] ip=<client-ip>:<server-ip>:<gwip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>

<server-ip>:服务器 IP 地址,也就是存放根文件系统主机的 IP 地址,那就是 Ubuntu 的 IP
地址,比如我的 Ubuntu 主机 IP 地址为 192.168.1.250。
<root-dir>:根文件系统的存放路径,比如我的就是/home/zuozhongkai/linux/nfs/rootfs。
<nfs-options>:NFS 的其他可选选项,一般不设置。
<client-ip>:客户端 IP 地址,也就是我们开发板的 IP 地址,Linux 内核启动以后就会使用
此 IP 地址来配置开发板。此地址一定要和 Ubuntu 主机在同一个网段内,并且没有被其他的设
备使用,在 Ubuntu 中使用 ping 命令 ping 一下就知道要设置的 IP 地址有没有被使用,如果不能
ping 通就说明没有被使用,那么就可以设置为开发板的 IP 地址,比如我就可以设置为
192.168.1.251。
<server-ip>:服务器 IP 地址,前面已经说了。
<gw-ip>:网关地址,我的就是 192.168.1.1。
<netmask>:子网掩码,我的就是 255.255.255.0。
<hostname>:客户机的名字,一般不设置,此值可以空着。
<device>:设备名,也就是网卡名,一般是 eth0,eth1….,正点原子的 I.MX6U-ALPHA 开
发板的 ENET2 为 eth0,ENET1 为 eth1。如果你的电脑只有一个网卡,那么基本只能是 eth0。
这里我们使用 ENET2,所以网卡名就是 eth0。
<autoconf>:自动配置,一般不使用,所以设置为 off。
<dns0-ip>:DNS0 服务器 IP 地址,不使用。
<dns1-ip>:DNS1 服务器 IP 地址,不使用。
根据上面的格式 bootargs 环境变量的 root 值如下:

root=/dev/nfs nfsroot=192.168.1.250:/home/zuozhongkai/linux/nfs/rootfs,proto=tcp rw
ip=192.168.1.251:192.168.1.250:192.168.1.1:255.255.255.0::eth0:off

“proto=tcp”表示使用 TCP 协议,“rw”表示 nfs 挂载的根文件系统为可读可写。启动开发
板,进入 uboot 命令行模式,然后重新设置 bootargs 环境变量,命令如下:

setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.250:
/home/zuozhongkai/linux/nfs/rootfs,proto=tcp rw ip=192.168.1.251:192.168.1.250:192.168.1.1:
255.255.255.0::eth0:off' //设置 bootargs
saveenv //保存环境变量

设置好以后使用“boot”命令启动 Linux 内核。如果没有启动进入根文件系统的话可以重启一次开发板试试。

 可以看出 ls 命令工作正常!那么是不是说明我们的 rootfs 就制作成功了呢?大家注意,在
进入根文件系统的时候会有下面这一行错误提示:

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

7.完善根文件系统

a.创建/etc/init.d/rcS 文件,輸入如下内容

1 #!/bin/sh
2 
3 PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
4 LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
5 export PATH LD_LIBRARY_PATH
6
7 mount -a //使用 mount 命令来挂载所有的文件系统,这些文件系统由文件/etc/fstab 来指定,
所以我们一会还要创建/etc/fstab 文件。
8 mkdir /dev/pts
9 mount -t devpts devpts /dev/pts //devpts 挂载到/dev/pts 目录中。
10
11 echo /sbin/mdev > /proc/sys/kernel/hotplug
12 mdev -s

第 11 和 12 行,使用 mdev 来管理热插拔设备,通过这两行,Linux 内核就可以在/dev 目录
下自动创建设备节点。关于 mdev 的详细内容可以参考 busybox 中的 docs/mdev.txt 文档。

chmod 777 rcS

设置好以后就重新启动 Linux 内核,出现

b. 创建/etc/fstab 文件

在 rootfs 中创建/etc/fstab 文件,fstab 在 Linux 开机以后自动配置哪些需要自动挂载的分区,
格式如下:

<file system> <mount point> <type> <options> <dump> <pass>

<file system>:要挂载的特殊的设备,也可以是块设备,比如/dev/sda 等等。
<mount point>:挂载点。
<type>:文件系统类型,比如 ext2、ext3、proc、romfs、tmpfs 等等。
<options>:挂载选项,在 Ubuntu 中输入“man mount”命令可以查看具体的选项。一般使
用 defaults,也就是默认选项,defaults 包含了 rw、suid、 dev、 exec、 auto、 nouser 和 async。
<dump>:为 1 的话表示允许备份,为 0 不备份,一般不备份,因此设置为 0。

<pass>:磁盘检查设置,为 0 表示不检查。根目录‘/’设置为 1,其他的都不能设置为 1,
其他的分区从 2 开始。一般不在 fstab 中挂载根目录,因此这里一般设置为 0。

按照上述格式,在fstab文件中输入如下内容:

1 #<file system> <mount point> <type> <options> <dump> <pass>
2 proc /proc proc defaults 0 0
3 tmpfs /tmp tmpfs defaults 0 0
4 sysfs /sys sysfs defaults 0 0

fstab 文件创建完成以后重新启动 Linux,没有任何提示错误信息。

但是还需要创建一个 /etc/inittab

c.创建/etc/inittab 文件

inittab 的详细内容可以参考 busybox 下的文件 examples/inittab。init 程序会读取/etc/inittab
这个文件,inittab 由若干条指令组成。每条指令的结构都是一样的,由以“:”分隔的 4 个段组
成,格式如下:

<id>:<runlevels>:<action>:<process>

<id>:每个指令的标识符,不能重复。但是对于 busybox 的 init 来说,<id>有着特殊意义。
对于 busybox 而言<id>用来指定启动进程的控制 tty,一般我们将串口或者 LCD 屏幕设置为控
制 tty。
<runlevels>:对 busybox 来说此项完全没用,所以空着。
<action>:动作,用于指定<process>可能用到的动作。如下所示:

 <process>:具体的动作,比如程序、脚本或命令等。

参考 busybox 的 examples/inittab 文件,我们也创建一个/etc/inittab,

1 #etc/inittab  
2 ::sysinit:/etc/init.d/rcS   //系统启动以后运行/etc/init.d/rcS 这个脚本文件。
3 console::askfirst:-/bin/sh   //将 console 作为控制台终端,也就是 ttymxc0。
4 ::restart:/sbin/init       //重启的话运行/sbin/init。
5 ::ctrlaltdel:/sbin/reboot    //按下 ctrl+alt+del 组合键的话就运行/sbin/reboot,重启系统。
6 ::shutdown:/bin/umount -a -r  //关机的时候执行/bin/umount,也就是卸载各个文件系统。
7 ::shutdown:/sbin/swapoff -a //关机的时候执行/sbin/swapoff,也就是关闭交换分区。

/etc/inittab 文件创建好以后就可以重启开发板即可,至此!根文件系统要创建的文件就已经
全部完成了。

8.根文件系统其他功能测试

a. 软件运行测试

我们使用 Linux 的目的就是运行我们自己的软件,我们编译的应用软件一般都使用动态库,
使用动态库的话应用软件体积就很小,但是得提供库文件,库文件我们已经添加到了根文件系
统中。我们编写一个小小的测试软件来测试一下库文件是否工作正常。

1 #include <stdio.h>
2 
3 int main(void)
4 {
5     while(1) {
6         printf("hello world!\r\n");
7         sleep(2);
8     }
9     return 0;
10 }
arm-linux-gnueabihf-gcc hello.c -o hello
file hello //查看 hello 的文件类型以及编码格式

输出

hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked……

 ARM 架构的,并且是动态链接的。

我们将其拷贝至到 rootfs/drivers 目录下,在开发板中输入如下命令来执行这
个可执行文件:

cd /drivers //进入 drivers 目录
./hello //执行 hello

结果如下图所示

b. 中文字符测试

b.1.设置 SecureCRT 使用 UTF-8 编码

b.2.创建中文文件

在 ubuntu 中向在 rootfs 目录新建一个名为“中文测试”的文件夹,然后在 SecureCRT 下查
看中文名能不能显示正确。输入“ls”命令。\

c. 开机自启动测试

进入根文件系统的时候会运行/etc/init.d/rcS 这个 shell 脚本,因此我们可以在这个脚本里面添加自启动相关内容

1 #!/bin/sh
2 PATH=/sbin:/bin:/usr/sbin:/usr/bin
3 LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
4 runlevel=S
5 umask 022
6 export PATH LD_LIBRARY_PATH runlevel
7 
8 mount -a
9 mkdir /dev/pts
10 mount -t devpts devpts /dev/pts
11
12 echo /sbin/mdev > /proc/sys/kernel/hotplug
13 mdev -s
14
15 #开机自启动
16 cd /drivers
17 ./hello &
18 cd /

以重启开发板,看看 hello 这个软件会不会自动运行,可以自动运行,说明设置成功。

d.外网连接测试

ping www.baidu.com

 可以看出,测试失败,提示 www.baidu.com 是个“bad address”,也就是地址不对,显然我
们的地址是正确的。之所以出现这个错误提示是因为 www.baidu.com 的地址解析失败了,并没
有解析出其对应的 IP 地址。我们需要配置域名解析服务器的 IP 地址,一般域名解析地址可以
设置为所处网络的网关地址,比如 192.168.1.1。也可以设置为 114.114.114.114,这个是运营商
的域名解析服务器地址。

在 rootfs 中新建文件/etc/resolv.conf,然后在里面输入如下内容:

1 nameserver 114.114.114.114
2 nameserver 192.168.1.1

//nameserver 表示这是个域名服务器,设置了两个域名服务器地址:
114.114.114.114 和 192.168.1.1

如果使用“udhcpc”命令自动获取 IP 地址,“udhcpc”命令会修改 nameserver 的值,一般是将其设置为对应的网关地址。修改好以后保存退出,重启开发板!

重启以后重新 ping 一下百度官网,成功。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值