1. 编译根文件系统
1.1 解压源代码压缩文件
1.2 修改Makefile
修改顶层目录下的Makefile,设置编译器和架构相关的变量
1.3 busybox 中文字符支持
busybox默认是不支持中文字符的,这样出现的问题就是中文文件的文件名会显示"???"这种
修改libbb/printable_string.c文件的FAST_FUNC printable_stringh函数
修改libbb/unicode.c文件中的unicode_conv_to_printable2函数
1.4 配置busybox
有三种配置方案:
- defconfig : 默认配置选项
- allyesconfig : 全选配置,也就是选中busybox中的所有功能
- allnoconfig : 最小配置
我们选择默认配置即可
1.5 使用图形化界面添加需要的配置
make menuconfig // 进入图形化配置界面
选择是否静态编译,静态编译的话就不需要库文件,但是编译出来的库会很大。我们不选择(因为采用静态编译的
话 DNS 会出问题!无法进行域名解析)
配置路径如下
Location: -> Settings ->Build static binary(no shard libs) // 不选中
继续配置如下:
Location: ->Settings ->vi-style line editing commands
继续配置:
Location: -> Linux Module Utilities -> Simplified modutils
默认会勾选,我们取消它
继续配置如下路径配置项:
Location: -> Linux System Utilities -> mdev (16kb) # 确保下面的全部选中
使能unicode编码和支持中文
Location: -> Settings -> Support Unicode # 选中 -> Check $LC_ALL, $LC_CTYPE and $LANG environment variables # 选中
1.6 编译busybox
使用命令make编译busybox
使用如下命名将根文件系统安装到指定目录(需要先创建该目录)
make install CONFIG_PREFIX=~/rootfs
2. 向根目录文件系统添加lib库
将交叉编译链里面的库拷贝到根文件系统下
2.1 在rootfs目录下添加/lib目录
2.2 找到自己的交叉编译链的安装位置
2.3 将工具链根目录/arm-linux-gnueabihf/libc/lib下的库文件拷贝到rootfs/lib/下
后面的“-d”表示拷贝符号链接
拷贝的文件中有个比较特殊的库文件:ld-linux-armhf.so.3, 他是一个链接文件,但在根文件系统中不能作为符号链接,否则的话在根文件系统中执行程序无法执行,我们需要将它变为本尊
先删除rootfs/lib下的ld-linux-armhf.so.3,在重新将链接工具库/arm-linux-gnueabihf/libc/lib的ld-linux-armhf.so.3拷贝过来
2.4 将工具链根目录/arm-linux-gnueabihf/lib下的库文件拷贝到rootfs/lib下
3. 向根目录添加usr/lib目录
3.1 创建usr/lib目录
3.2 将工具链根目录/arm-linux-gnueabihf/libc/usr/lib下的库文件拷贝到rootfs/usr/lib下
4. 创建其他文件夹
4.1 在根目录下创建重要的文件夹
4.2 创建/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
给予权限
chmod 777 rcS
4.3 创建/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
file system: 要挂载的设备
mount point : 挂载点
type: 挂载选项,在 Ubuntu 中输入“man mount”命令可以查看具体的选项。一般使用 defaults,也就是默认选项,defaults 包含了 rw、suid、 dev、 exec、 auto、 nouser 和 async。
dump: 1表示允许备份,0表示不备份。一般不需要
pass : 是否进行磁盘检查。一般不需要
4.4 创建/etc/inittab文件
/etc/inittab文件写的指令格式
<id>:<runlevels>:<action>:<process>
<id>:每个指令的标识符,不能重复。但是对于 busybox 的 init 来说,有着特殊意义。对于 busybox 而言用来指定启动进程的控制 tty,一般我们将串口或者 LCD 屏幕设置为控制 tty。
<runlevels>:对 busybox 来说此项完全没用,所以空着。
<action>:动作,用于指定可能用到的动作。
动作 | 描述 |
sysinit | 在系统初始化的时候 process 才会执行一次。 |
respawn | 当 process 终止以后马上启动一个新的。 |
askfirst | 和 respawn 类似,在运行 process 之前在控制台上显示“Please press Enter to activate this console.”。只要用户按下“Enter”键以后才会执行 process。 |
wait | 告诉 init,要等待相应的进程执行完以后才能继续执行。 |
once | 仅执行一次,而且不会等待 process 执行完成。 |
restart | 当 init 重启的时候才会执行 procee。 |
ctrlaltdel | 当按下 ctrl+alt+del 组合键才会执行 process。 |
shutdown | 关机的时候执行 process。 |
- <process>:具体的动作,比如程序、脚本或命令等。
/etc/inittab填入如下内容
# <id>:<runlevels>:<action>:<process> ::sysinit:/etc/init.d/rcS console::askfirst:-/bin/sh ::ctraltdel:/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,也就是关闭交换分区。
5. 测试
测试我是选择的网络挂载根文件系统来测试的。
首先需要安装nfs服务器,将路径配置为我们刚刚创建的rootfs
配置uboot里面的bootargs变量,指定其为网络NFS挂载文件系统,格式如下
root=/dev/nfs nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>] ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>
<server-ip>:服务器 IP 地址,也就是存放根文件系统主机的 IP 地址,那就是 Ubuntu 的 IP
地址,比如我的 Ubuntu 主机 IP 地址为 192.168.9.9。
<root-dir>:根文件系统的存放路径,比如我的就是/home/hxd/rootfs。
<nfs-options>:NFS 的其他可选选项,一般不设置。
<client-ip>:客户端 IP 地址,也就是我们开发板的 IP 地址,Linux 内核启动以后就会使用此 IP 地址来配置开发板。此地址一定要和 Ubuntu 主机在同一个网段内,并且没有被其他的设备使用,在 Ubuntu 中使用 ping 命令 ping 一下就知道要设置的 IP 地址有没有被使用,如果不能ping 通就说明没有被使用,那么就可以设置为开发板的 IP 地址,比如我就可以设置为192.168.9.6。
<server-ip>:服务器 IP 地址,前面已经说了。
<gw-ip>:网关地址,我的就是 192.168.9.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 地址,不使用。
按照实际情况,我的配置为:
root=/dev/nfs nfsroot=192.168.9.9:/home/hxd/rootfs,proto=tcp rw ip=192.168.9.6:192.168.9.9:192.168.9.1:255.255.255.0::eth0:off
故设置bootargs的命令为:
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.9.9:/home/hxd/rootfs,proto=tcp rw ip=192.168.9.6:192.168.9.9:192.168.9.1:255.255.255.0::eth0:off';saveenv
输入boot命令,成功!