LV09-03-linux-02-linux内核移植
本文主要是linux——内核移植的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
Windows | windows11 |
Ubuntu | Ubuntu16.04的64位版本 |
VMware® Workstation 16 Pro | 16.2.3 build-19376536 |
SecureCRT | Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日 |
Linux开发板 | 华清远见 底板: FS4412_DEV_V5 核心板: FS4412 V2 |
u-boot | 2013.01 |
点击查看本文参考资料
参考方向 | 参考原文 |
Linux内核移植 | 实验7 Linux内核移植 |
网卡驱动移植 | 实验8 网卡驱动移植 |
根文件系统移植 | 实验9 根文件系统移植 |
驱动开发指南 | i.MX6ULL Linux阿尔法开发板资料 |
Linux内核官网 | The Linux Kernel Archives |
BusyBox官网 | BusyBox |
点击查看相关文件下载
文件 | 下载链接 |
roofs.rar | 根文件系统(通过nfs共享给开发板的时候用) |
一、文件准备
1. linux
内核源码
1.1 源码获取途径
关于linux
内核的官方源码我们可以从这里获取:Index of /pub/linux/kernel/
1.2 获取源码文件
我下载的是linux-3.14.tar.xz
这个压缩包并将其存放于ubuntu
下的共享文件夹下,路径为:
1 | /mnt/hgfs/Sharedfiles/test |
1.3 拷贝解压
然后我们可以将这个源码文件拷贝解压到ubuntu
中,方便后边编译,我们可以在终端执行以下命令:
1 | cp /mnt/hgfs/Sharedfiles/test/linux-3.14.tar.xz ~/6temp/ # 拷贝压缩包 |
然后我们可以得到下边这些文件(通过ls
命令查看):
点击查看部分文件说明
- 平台相关
即与CPU
架构或开发板硬件相关的源码,硬件的改动对应的代码也需要进行修改。
arch | 与CPU架构相关的源代码 |
- 平台无关
block | 磁盘设备的支持,就是块设备相关目录 |
crypto | 加密相关 |
drivers | 设备驱动 |
Documentation | 帮助文档 |
firmware | 固件 |
fs | 文件系统 |
include | 头文件 |
init | 内核初始化 |
ipc | 进程间通信 |
kernel | 内核核心调度机制等 |
lib | 库相关目录 |
mm | 内存管理 |
net | 网络协议 |
samples | 例程 |
scripts | 工具、脚本等 |
security | 安全 |
sound | 音频处理 |
tools | 工具 |
usr | 打包与压缩,与initramfs相关的目录,用于生成initramfs |
virt | 提供虚拟机技术(KVM) |
还有一些其他的文件,这里就不再写了。
2. Busybox
源码
2.1 源码获取途径
我们可以从这里获取Busybox
的源码:Index of /downloads (busybox.net)
2.2 获取源码文件
我下载的是busybox-1.22.1.tar.bz2
这个压缩包并将其存放于ubuntu
下的共享文件夹下,路径为:
1 | /mnt/hgfs/Sharedfiles/test |
2.3 拷贝解压
然后我们可以将这个源码文件拷贝解压到ubuntu
中,方便后边编译,我们可以在终端执行以下命令:
1 | cp /mnt/hgfs/Sharedfiles/test/busybox-1.22.1.tar.bz2 ~/6temp/ # 拷贝压缩包 |
然后我们可以得到下边这些文件(通过ls
命令查看):
3. rootfs
3.1 文件获取
这里是直接制作好了的根文件系统相关文件有些文件可以直接从这里边拷贝,我们直接从这里下载并解压:根文件系统(roofs.rar,通过nfs共享给开发板的时候用)
下载完毕后,存放于ubuntu
的共享文件夹中:
1 | /mnt/hgfs/Sharedfiles/test |
我们可直接在windows
下将压缩文件解压,我们将得到一个名为rootfs.tar.bz2
的压缩包
3.2 拷贝解压
然后我们可以将这个文件拷贝解压到ubuntu
中,方便后边编译,我们可以在终端执行以下命令:
1 | cp /mnt/hgfs/Sharedfiles/test/roofs/rootfs.tar.bz2 ~/6temp/ # 拷贝压缩包 |
然后我们可以得到下边这些文件(通过ls
命令查看):
点击查看部分目录说明
bin | shell命令(elf格式)(通过busybox编译生成) |
dev | 设备文件(内核启动后会将设备信息写入该目录) |
etc | 内核配置文件 |
lib | 共享库(elf格式)(从交叉编译工具链中获取) |
linuxrc | 内核运行的第一个应用程序(通过busybox编译生成) |
mnt | 挂载目录(非必要) |
proc | 进程相关文件(内核启动后会将进程信息写入该目录) |
root | 超级用户家目录(非必要) |
sbin | 系统管理shell命令(elf格式)(通过busybox编译生成) |
sys | 驱动相关文件(内核启动后会将驱动信息写入该目录) |
usr | shell命令(elf格式)(通过busybox编译生成) |
二、Linux
内核移植
首先我们要进入Linux
源码目录,后边所有的命令都在源码的顶层目录下进行:
1 | cd ~/6temp/linux-3.14/ |
1. 指定交叉编译工具
linux
内核源码并不知道我们使用的处理器架构及交叉编译工具是什么,这里我们需要自己在Makefile
中指定,我们通过下边的命令打开顶层Makefile
文件:
1 | vim Makefile |
找到下边的语句(这个3.14
版本的话应该是在198
行):
1 | ARCH ?= $(SUBARCH) |
将其修改为:
1 | ARCH ?= arm |
【注意】arm-none-linux-gnueabi-
后边不要有多余的空格。
2. linux
内核编译
2.1 内核配置
2.1.1 配置文件
linux
内核源码的arch/arm/configs
目录下下对各个厂商的soc
都有一个默认配置文件,这个默认的配置文件命名格式为:
1 | <soc_name>_defconfig |
当我们执行一个make <soc_name>_defconfig
命令的时候,就会将对应的配置文件也就是<soc_name>_defconfig
中的信息导入到源码顶层目录下的.config
。配置文件中的语句有两种:
1 | CONFIG_xxx=y |
CONFIG_xxx=y
:表示内核选中了该功能,内核编译时就会将该功能对应的代码编译,内核的体积也会增大。#CONFIG_xxx is not set
:表示内核没有选中该功能,内核编译时该功能对应的代码不会被编译,内核的体积也会减小。
2.1.2 修改配置文件
默认配置只能保证内核拥有最基本的功能,我们需要根据自己的实际需求对内核做进一步的配置,修改soc
配置文件的话有两种方式,一种是直接修改.config
文件或者<soc_name>_defconfig
文件,但是这种方式并不推荐,因为我们修改一个配置,这个配置可能相应的依赖另外好几个配置,打开这一个配置,需要打开所有依赖的配置,但是很多时候我们并不能准确的打开所有的依赖配置;方式二就是通过图形界面来修改配置,这种方式可以直接解决依赖问题。
我们通过以下命令打开图形配置界面:
1 | make menuconfig |
【注意】make menuconfig
本质还是修改了.config
文件。
点击查看可能出现的问题
- 问题一
这是因为我们没有安装对应的图形库,我们执行以下命令安装相应的图形库即可:
1 | sudo apt-get install libncurses5-dev |
- 问题二
这是因为我们的终端太小了,拉大一点就可以了,上边提示说,必须至少有19
行80
列才可以。
然后我们会看到如下界面:
这样便是正常打开了图形配置界面。
具体的操作说明,在图形界面上都有,这里主要介绍一下配置选项的两种类型:
[]
有两种状态
输入Y
,显示*
,内核中该功能被选中,相关代码会被编译进内核。
输入N
,显示 <space>
(就是一个空格),内核中该功能不被选中,相关代码不会被编译进内核。
< >
有三种状态
输入Y
,显示*
,内核中该功能被选中,相关代码会被编译进内核。
输入N
,显示 <space>
(就是一个空格),内核中该功能不被选中,相关代码不会被编译进内核。
输入M
,显示M
,内核中该功能被选为模块(被编译为独立的模块)。
【注意】我们可以通过<space>
(即空格按键来更改选项的状态)。
2.2 指定使用的处理器
和uboot
一样,在编译Linux
内核之前要先配置Linux
内核。每个板子都有其对应的默认配置文件,这些默认配置文件保存在 arch/arm/configs
目录中。
导入当前处理器的默认配置的make
命令格式为:
1 | make <soc_name>_defconfig |
例如,我们现在导入exynos_defconfig
1 | make exynos_defconfig |
然后便会有以下提示信息:
额,并未做任何修改的linux
在配置的时候不知道这里为啥有一个警告,不过似乎对后边并没有什么影响。
2.3 编译内核
接下来我们就可以编译linux
内核了,我们在终端执行以下命令:
1 | make uImage -j4 # 4 核同时进行编译,会快那么一点点 |
【注意】这个命令用于编译内核(编译选为*
的选项到内核)。
点击查看可能出现的问题
要是第一次在ubuntu
中编译linux
内核的话,不出意外应该会报以下错误:
这里会提示少一个mkimage
命令,该命令可在uboot
源码中u-boot-2013.01/tools/
目录下获取(注意必须是编译后的uboot
)。
- 我们将这个工具拷贝到我们的
ubuntu
中
1 | sudo cp ~/5linux/u-boot-2013.01/tools/mkimage /usr/bin/ |
- 添加可执行权限
1 | sudo chmod 777 /usr/bin/mkimage |
然后回到linux
源码的顶层目录下重新编译即可。
要是编译成功的话会有以下信息:
2.4 编译内核模块
我们在终端执行以下命令:
1 | make modules -j4 |
【注意】这个命令用于编译内核模块((编译选为M
的选项为独立模块)。
例如,我们将DM9000 support
配置更改为M
状态,该选项位于:
1 | Device Drivers ---> |
我们将其选为M
状态,然后执行上边的内核模块编译命令,然后我们进入下边的目录下:
1 | drivers/net/ethernet/davicom |
会发现生成了dm9000.ko
文件,这个文件就是kernel object
文件(内核模块),该文件作用是把内核的部分功能移动到内核外边,需要的时候插入内核,不需要时卸载。
3. 设备树编译
3.1 添加设备树源码文件
在我们下载的linux
内核源码中并没有我们使用的fs4412
开发板平台的设备树文件,这里我们从源码支持的平台中找一个硬
件与这个开发板最类似的,在其基础上进行修改,这里我们参考的是samsung
公司的origen
,拷贝origen
的设备树并将其重命名。
1 | cp arch/arm/boot/dts/exynos4412-origen.dts arch/arm/boot/dts/exynos4412-fs4412.dts |
3.2 修改相应Makefile
arch/arm/boot/dts/Makefile
修改相应的makefile
文件,使我们添加的设备树源码文件可以参与编译。我们打开相应的Makefile
文件,然后找到以下语句:
1 | exynos4412-origen.dtb \ |
在该语句后添加如下内容:
1 | exynos4412-fs4412.dtb \ |
3.3 编译设备树
我们回到linux
内核源码顶层目录下,执行以下命令:
1 | make dtbs -j4 |
【注意】该命令会将设备树源文件dts
编译为二进制文件dtb
。
显示如下信息表示编译成功,即在arch/arm/boot/dts/
目录下生成了exynos4412-fs4412.dtb
。
4. 内核启动测试
上边我们已经编译好了内核和设备树,下边我们就测试一下我们自己编译的内核能否启动。之前的时候在学习linux
内核加载的时候,我们在ubuntu
的~/3tftp/fs4412
和~/4nfs
中已经放入了相关的所有文件:
- 拷贝相关文件
我们将我们自己编译得到的uImage
文件和exynos4412-fs4412.dtb
拷贝到~/3tftp/fs4412
中,根文件系统的话还是先使用之前的。
1 | cp arch/arm/boot/uImage ~/3tftp/fs4412/ |
- 设置
uboot
变量
这一步我们之前应该设置过了,我们从eMMC
启动uboot
,从tftp
下载linux
内核和设备树文件,从nfs
挂载根文件系统,相应的两个参数设置如下:
1 | fs4412 # print bootcmd |
- 重启相关服务
我们重启一下tftp
和nfs
服务,在ubuntu
终端执行:
1 | sudo service tftpd-hpa restart |
- 重启开发板
最后就是重启开发板,观察现象了。这样的话其实我们会发现内核可以正常启动了,但是到后边就崩溃卡死了:
原因在于我们在该实验中什么都没有配置,而其他功能都保持默认选项,内核默认配置中没选配我们使用的网卡驱动、nfs
等功能,所以在挂载根文件系统时导致内核崩溃,所以后续我们还需要配置网卡驱动、nfs
等。不过这一部分的主要目的就是实现内核的启动,能出现这些提示已经表明我们的目的达到了。
三、基本驱动移植
1. 串口驱动
串口驱动的移植较为简单,我们只需要在linux
内核配置图形界面打开相应的配置即可。
1 | System Type ---> |
我们将将System Type
菜单下的S3C UART to use for low-level messages
修改为2
(即使用UART2
),初始的时候是3
。
2. 网卡驱动
2.1 修改内核配置
我们执行以下命令打开图形配置界面:
1 | make menuconfig |
- 给内核选配
DM9000
网卡驱动,然后选择Save
保存
1 | Device Drivers ---> |
- 选配
TCP
相关的网络协议(部分功能默认已经选配),然后选择Save
保存
因为内核要使用NFS
去挂载根文件系统,而NFS
是基于TCP
协议实现的,所以这里需要配置一下TCP
相关网络协议:
1 | [*] Networking support ---> |
- 选配
NFS
客户端及相关功能
因为内核要使用NFS
去挂载根文件系统,所以需要给内核选配NFS
客户端的相关功能:
1 | File systems ---> |
设置完成后通过方向键选择Save
保存即可,然后选择Exit
退出该配置界面。
2.2 修改设备树
arch/arm/boot/dts/exynos4412-fs4412.dts
接下来我们需要在设备树中添加网卡的硬件信息,我们打开文件exynos4412-fs4412.dts
,在文件的末尾处最后一个花括号之前添加以下内容(即要写在根节点之内):
1 | srom-cs1@5000000 { |
2.3 修改时钟配置
drivers/clk/clk.c
我们需要忽略一些无关的时钟,找到以下语句:
1 | static bool clk_ignore_unused; |
将其修改为以下内容:
1 | static bool clk_ignore_unused=true; |
2.4 修改eMMC
配置
drivers/mmc/core/mmc.c
我们需要找到以下语句:
1 | if (card->ext_csd.rev > 7) { |
将其修改为以下内容:
1 |
|
3. 编译内核和设备树
上边我们已经移植好了串口和网卡驱动,然后就是重新编译内核和设备树啦,我们在终端执行以下命令:
1 | make uImage -j4 |
4. 内核启动测试
- 拷贝相关文件
我们将我们自己编译得到的uImage
文件和exynos4412-fs4412.dtb
拷贝到~/3tftp/fs4412
中,根文件系统的话还是先使用之前的。
1 | cp arch/arm/boot/uImage ~/3tftp/fs4412/ |
- 设置
uboot
变量
这一步我们之前应该设置过了,我们从eMMC
启动uboot
,从tftp
下载linux
内核和设备树文件,从nfs
挂载根文件系统,相应的两个参数设置如下:
1 | fs4412 # print bootcmd |
- 重启相关服务
我们重启一下tftp
和nfs
服务,在ubuntu
终端执行:
1 | sudo service tftpd-hpa restart |
- 重启开发板
最后就是重启开发板,观察现象了,若成功挂载文件系统,则说明我们已经成功配置了网卡。
四、根文件系统移植
根文件系统移植我们主要是使用Busybox
来进行根文件系统的制作,前边我们已经准备好了相关的文件并解压了,我们进入Busybox
源码的顶层目录:
1 | cd ~/6temp/busybox-1.22.1/ |
1. 配置busybox
busybox
具有和linux
内核类似的图形配置界面,我们可以通过下边的命令进入图形配置界面:
1 | make menuconfig |
配置界面如下:
我们在进行根文件系统制作的时候需要先配置一下busybox
,配置如下信息即可:
1 | Busybox Settings ---> |
配置完成后通过方向键选择Exit
退出,并保存配置信息。
2. 编译busybox
上一步配置完成就可以开始编译busybox
了,我们可以执行如下命令:
1 | make |
这个比较简单,只需要一个make
命令就可以开始编译了,编译完成后,会在源码的顶层目录下生成一个busybox
文件。
3. 安装busybox
上一步只是进行了编译,我们还需要安装busybox
,我们在终端执行:
1 | make install |
安装完成后会有如下提示信息:
若未指定安装的目录,我们会发现在busybox
源码顶层目录下会生成一个_install
目录,我们看一下这个目录中都有什么:
1 | ls _install -ah |
我们会发现有如下文件:
这里边就是我们所需要的根文件系统,包含了根文件系统中所需的shell
命令文件。
4. 添加lib
库
4.1 拷贝lib
库
我们还需要将交叉编译工具链中的库文件拷贝到_install
目录下:
1 | cp -a ~/2software/gcc-4.6.4/arm-arm1176jzfssf-linux-gnueabi/lib/ ./_install/ |
【注意】cp
命令要加上-a
选项,这个选项通常在复制目录时使用,它保留链接、文件属性,并复制目录下的所有内容。因为我们要靠拷贝的文件中有几个比较特殊的库文件,例如 ld-linux.so.3
,这些库文件是符号链接,直接拷贝的话会丢失属性,所以这里要加上-a
选项。
4.2 删除lib
静态库
我们执行以下命令删除lib
中的静态库:
1 | sudo rm ./_install/lib/*.a |
4.3 删除共享库中符号表
我们还需要删除剩下的共享库中的符号表,该操作需要在root
用户中才能操作,这里需要注意我们使用的命令strip
也需要是交叉编译器中的命令,而这个命令在root
用户下需要带上绝对路径:
1 | sudo su # 切换到root用户 |
我们可以使用以下命令查看”瘦身”前后该目录大小的变化:
1 | du -mh _install/lib |
“瘦身”完成后没我们可以通过下边的命令来查看是否已经”瘦身”完毕,我们随便查看一个文件:
1 | file _install/lib/ld-2.17.so |
然后我们会得到如下提示信息:
1 | _install/lib/ld-2.17.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, stripped |
stripped
就表明该库已经删除了符号表,已经完成了”瘦身”。
5. 创建其他目录
在根文件系统中还需要创建其他文件夹,如dev
、proc
、mnt
、 sys
、 tmp
和 root
等:
1 | cd _install/ |
创建完成后,我们的根文件系统目录如下图所示:
我们刚才创建的几个都是空目录,其实可以发现我们还是少了一个etc
目录,我们这里先不创建,一会先进行测试看看没有这个目录会有什么事情发生。
6. 根文件系统初步测试
我们到安装了busybox
的目录中,方便后续操作:
1 | cd ~/6temp/busybox-1.22.1/_install/ |
- 删除原来的根文件系统
1 | sudo rm -rf ~/4nfs/rootfs/* |
- 拷贝我们自己制作的根文件系统到相应的挂载目录
1 | sudo cp -rf ./* ~/4nfs/rootfs/ |
- 重启开发板
注意我们使用的uboot
参数与上边linux
内核移植时一样,从tftp
加载linux
内核和设备树,从nfs
挂载根文件系统。
从图中我们会发现,根文件系统正常挂载了,并且ls
命令也可正常运行,但是有一个错误提示:
1 | can't run '/etc/init.d/rcS': No such file or directory |
这个错误提示其实很简单,说是无法运行“/etc/init.d/rcS
这个文件,因为这个文件不存在。
7. 完善根文件系统
7.1 etc
目录介绍
7.1.1 目录结构
刚才的错误提示就是提示我们缺少/etc/init.d/rcS
文件,但是我们打开以前已经制作好的根文件目录rootfs
看一下etc
目录下都有哪些文件(前边准备文件的时候有解压过这个目录):
1 | cd ~/6temp/rootfs/etc/ # 进入 etc 目录 |
然后我们会得到如下信息:
7.1.2 rcS
文件
rcS
是个shell
脚本,Linux
内核启动以后需要启动一些服务,而rcS
就是规定启动哪些文件的脚本文件。该文件应改位于etc/init.d/rcS
文件,我们打开这个文件看一下都有什么:
1 | vim ~/6temp/rootfs/etc/init.d/rcS |
我们会看到如下信息:
1 | !/bin/sh |
- 第
1
行:表示这是一个shell
脚本。 - 第
2
行:使用mount
命令来挂载所有的文件系统,这些文件系统由文件etc/fstab
来指定。 - 第
3
行和第4
行:使用mdev
来管理热插拔设备,通过这两行,Linux
内核就可以在/dev
目录下自动创建设备节点。关于mdev
的详细内容可以参考busybox
中的docs/mdev.txt
文档。
【说明】
(1)这只是我们自己做的根文件系统中的rcS
文件,这个是比较简单的,只有这么几行,但是Ubuntu
或者其他大型Linux
操作系统中的rcS
文件,会更加的复杂,一般来说复杂的rcS
文件也是借助其他工具创建的,比如 buildroot
等。
(2)etc/init.d/rcS
这个文件是需要有可执行文件才可以运行的。
7.1.3 fstab
文件
etc/fstab
文件在Linux
开机以后自动配置哪些需要自动挂载的分区,该文件中内容的格式如下:
1 | <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
。
我们可以打开一个创建好的文件看一下:
1 | vim ~/6temp/rootfs/etc/fstab |
我们会看到如下内容:
1 | device mount-point type options dump fsck orde |
7.1.4 inittab
文件
inittab
的详细内容可以参考busybox
下的文件examples/inittab
。init
程序会读取etc/inittab
这个文件,inittab
由若干条指令组成。每条指令的结构都是一样的,由以:
分隔的 4个段组成,格式如下:
1 | <id>:<runlevels>:<action>:<process> |
id
:每个指令的标识符,不能重复。但是对于busybox
的init
来说,id
有着特殊意义。对于busybox
而言id
用来指定启动进程的控制tty
,一般我们将串口或者LCD
屏幕设置为控制tty
。runlevels
:对busybox
来说此项完全没用,所以可以空着。action
:动作,用于指定process
可能用到的动作。
点击查看busybox支持的动作
动作 | 描述 |
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
:具体的动作,比如程序、脚本或命令等。
例如,我们打开一个创建好了的文件看一下:
1 | vim ~/6temp/rootfs/etc/inittab |
我们会看到以下信息:
1 | ::sysinit:/etc/init.d/rcS |
- 第
1
行,系统启动以后运行/etc/init.d/rcS
这个脚本文件。 - 第
2
行,系统启动以后,在运行process
之前在控制台上显示提示信息,只有用户按下Enter
键以后才会执行process
。 - 第
3
行,系统启动以后,重启的话运行/sbin/init
。 - 第
4
行,按下ctrl+alt+del
组合键的话就运行/sbin/reboot
,也就是说ctrl+alt+del
组合键可以用于重启系统。
7.2 etc
目录创建
我们可以自己按照创建好的etc
目录文件内容逐个创建文件,也可以拷贝已经做好的etc
目录,后续再修改相关文件,以达到自己的预期效果。
- 这里我们拷贝已经创建好的
etc
目录:
1 | cp -r ~/6temp/rootfs/etc ~/6temp/busybox-1.22.1/_install/ |
- 给
rcS
文件添加可执行权限
1 | sudo chmod +x ~/6temp/busybox-1.22.1/_install/etc/init.d/rcS |
7.3 根文件系统测试
- 删除原来的根文件系统
1 | sudo rm -rf ~/4nfs/rootfs/* |
- 拷贝我们自己制作的根文件系统到相应的挂载目录
1 | sudo cp -rf ~/6temp/busybox-1.22.1/_install/* ~/4nfs/rootfs/ |
- 重启开发板
这一次我们会发现启动后没有错误提示了:
8. busybox
中文字符支持
我们是通过nfs
挂载的根文件系统,我们可以在ubuntu
的相关目录下创建一个中文命名的目录,例如:
1 | cd ~/4nfs/rootfs/ |
然后我们会看到ubuntu
下目录详情如下:
1 | bin dev etc lib linuxrc mnt proc root sbin sys tmp usr var 桌面 |
然而我们到SecureCRT
中,看一下根目录:
1 | ls |
我们会发现并不支持中文而中中文目录显示为?
。老版本的busybox
是支持中文的,但是不知道从哪个版本开始busybox
中的shell
命令对中文输入即显示做了限制,即使内核支持中文但在shell
下也依然无法正确显示。这个时候就需要修改busybox
源码了。
我们先进入busybox
源码顶层目录:
1 | cd ~/6temp/busybox-1.22.1/ |
8.1 printable_string.c
文件修改
首先我们需要修改libbb/printable_string.c
文件,我们打开该文件后,会发现这里边只有一个printable_string
函数,该函数中有这么几条语句:
1 | /* 下边if出现在34行 */ |
通过这几个语句我们知道,当字符大于0X7F
以后就跳出去了。如果支持UNICODE
码的话,当字符大于0X7F
就直接输出?
。我们将上边的两个if
语句进行修改:
1 | /* 下边if出现在34行(将这个if注释掉) */ |
这两处修改主要是为了禁止字符大于0X7F
以后break
和输出?
。
8.2 unicode.c
文件修改
我们打开libbb/unicode.c
文件,然后找到unicode_conv_to_printable2
函数,在该函数中有这么几行:
1 | /* 下边的这个三目运算符语句出现在 1022 行*/ |
1022
行表示当字符大于0X7F
以后,*d++
就为?
,1030
行和1031
行表示,当字符大于0X7F
以后,*d
也为?
。我们将其修改为以下内容:
1 | /* 下边的这个三目运算符语句出现在 1022 行*/ |
8.3 busybox
配置
我们执行以下命令打开busybox
的图形配置界面:
1 | make menuconfig |
然后我们需要使能busybox
的unicode
编码以支持中文,配置路径如下:
1 | Busybox Settings ---> |
然后退出,一定要记得保存。
8.4 重新制作根文件系统
按照前边的步骤重新制作根文件系统即可。