Skip to content

LV105-busybox构建

这里使用 busybox-1.36.1版本,在busybox - BusyBox这里可以在线看源码,我们找到这个标签:1_36_stable,然后可以在这里查看这个版本的源码:tree/1_36_stable

一、根文件系统移植

根文件系统移植我们主要是使用 Busybox 来进行根文件系统的制作,前边我们已经准备好了相关的文件并解压了,我们进入 Busybox 源码的顶层目录:

shell
cd ~/7Linux/busybox-1.36.1

1. 配置 busybox

与我们编译 Uboot、 Linux kernel 一样,我们要先对 busybox 进行默认的配置,有以下几种配置选项:

shell
make defconfig    # 缺省配置,也就是默认配置选项。
make allyesconfig # 全选配置,也就是选中 busybox 的所有功能。
make allnoconfig  # 最小配置。

我们一般使用 默认配置 即可,注意这里一定要先配置一下再编译,否则最后编译出来的根文件系统可能会少很多命令。默认配置结束后我们就可以进行一些其他的配置了,busybox 具有和 linux 内核类似的图形配置界面,我们可以通过下边的命令进入图形配置界面:

shell
make menuconfig

1.1 交叉编译器配置

配置界面如下:

shell
 BusyBox 1.36.1 Configuration
 ──────────────────────────────────────────────────────────────────────────────
  ┌─────────────────────────────── Settings ────────────────────────────────┐
  Arrow keys navigate the menu.  <Enter> selects submenus --->.  
  Highlighted letters are hotkeys.  Pressing <Y> includes, <N> excludes,  
  <M> modularizes features.  Press <Esc><Esc> to exit, <?> for Help, </>  
  for Search.  Legend: [*] built-in  [ ] excluded  <M> module  < >
 ┌↑(-)─────────────────────────────────────────────────────────────────┐  
 │--- Build Options  
 │[ ] Build static binary (no shared libs)                             │ │  
 │[ ]   Build position independent executable  
 │[ ] Force NOMMU build  
 │[ ] Build shared libbusybox  
(arm-linux-gnueabihf-) Cross compiler prefix  
()  Path to sysroot  
()  Additional CFLAGS  
()  Additional LDFLAGS  
()  Additional LDLIBS  
 └↓(+)─────────────────────────────────────────────────────────────────┘  
  ├─────────────────────────────────────────────────────────────────────────┤  
                    <Select>    < Exit >    < Help >  
  └─────────────────────────────────────────────────────────────────────────┘

我们在进行根文件系统制作的时候需要先配置一下 busybox 使用的编译器,配置如下信息即可:

shell
Busybox Configuration
    Busybox Settings  --->
		--- Build Options
			(arm-linux-gnueabihf-) Cross Compiler prefix

配置完成后通过方向键选择 Exit 退出,并保存配置信息。我这里使用的是 gcc version 8.3.0,交叉编译器前缀为 arm-linux-gnueabihf-,直接使用下边的命令就能看到交叉编译器的版本啦:

shell
sumu@sumu-virtual-machine:~/7Linux/busybox-1.36.1$ arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 8.3.0
Copyright © 2018 Free Software Foundation, Inc.
本程序是自由软件;请参看源代码的版权声明。本软件没有任何担保;
包括没有适销性和某一专用目的下的适用性担保。

1.2 动态编译配置

静态编译的话就不需要库文件,但是编译出来的库会很大。动态编译的话要求根文件系统中有库文件,但是编译出来的 busybox 会小很多。正点原子的资料中写到这里我们不能采用静态编译,因为采用静态编译的话 DNS 会出问题,无法进行域名解析, 我就暂时先按这个来啦。

shell
Busybox Configuration
    Busybox Settings  --->
        Build Options  --->
			[ ] Build static binary (no shared libs)

保证这个选项不要选中即可。

shell
 BusyBox 1.36.1 Configuration
 ──────────────────────────────────────────────────────────────────────────────
  ┌─────────────────────────────── Settings ────────────────────────────────┐
  Arrow keys navigate the menu.  <Enter> selects submenus --->.  
  Highlighted letters are hotkeys.  Pressing <Y> includes, <N> excludes,  
  <M> modularizes features.  Press <Esc><Esc> to exit, <?> for Help, </>  
  for Search.  Legend: [*] built-in  [ ] excluded  <M> module  < >
 ┌↑(-)─────────────────────────────────────────────────────────────────┐  
 │[ ] Support NSA Security Enhanced Linux  
 │[ ] Clean up all memory before exiting (usually not needed)          │ │  
 │[*] Support LOG_INFO level syslog messages  
 │--- Build Options  
 │[ ] Build static binary (no shared libs)                             │ │  
 │[ ]   Build position independent executable  
 │[ ] Force NOMMU build  
 │[ ] Build shared libbusybox  
(arm-linux-gnueabihf-) Cross compiler prefix  
()  Path to sysroot  
 └↓(+)─────────────────────────────────────────────────────────────────┘  
  ├─────────────────────────────────────────────────────────────────────────┤  
                    <Select>    < Exit >    < Help >  
  └─────────────────────────────────────────────────────────────────────────┘

1.3 vi 编辑器配置

shell
Busybox Configuration
    Busybox Settings  --->
		--- Library Tuning
			[*] Command line editing            # 选了这个下边的选项才会出来
			[*]   vi-style line editing commands

配置界面如下:

shell
 BusyBox 1.36.1 Configuration
 ──────────────────────────────────────────────────────────────────────────────
  ┌─────────────────────────────── Settings ────────────────────────────────┐
  Arrow keys navigate the menu.  <Enter> selects submenus --->.  
  Highlighted letters are hotkeys.  Pressing <Y> includes, <N> excludes,  
  <M> modularizes features.  Press <Esc><Esc> to exit, <?> for Help, </>  
  for Search.  Legend: [*] built-in  [ ] excluded  <M> module  < >
 ┌↑(-)─────────────────────────────────────────────────────────────────┐  
(4) Copy buffer size, in kilobytes  
 │[*] Use clock_gettime(CLOCK_MONOTONIC) syscall  
 │[*] Use ioctl names rather than hex values in error messages  
 │[*] Command line editing  
(1024) Maximum length of input  
 │[*]   vi-style line editing commands  
(255) History size  
 │[*]   History saving  
 │[ ]     Save history on shell exit, not after every command  
 │[*]   Reverse history search  
 └↓(+)─────────────────────────────────────────────────────────────────┘  
  ├─────────────────────────────────────────────────────────────────────────┤  
                    <Select>    < Exit >    < Help >  
  └─────────────────────────────────────────────────────────────────────────┘

1.4 Simplified modutils 配置

shell
Busybox Configuration
	Linux Module Utilities  ---> 
		[ ] Simplified modutils
		[*]   insmod
        [*]   rmmod
        [*]   lsmod
        [*]     Pretty output
        [*]   modprobe
        [*]     Blacklist support
        [*]   depmod

确保 Simplified modutils 这个选项没有被选中,不选中这个选项的时候下边几个选项会显示,下边几个选项是与 linux 模块加载卸载相关的,一定要选为 *。

shell
BusyBox 1.36.1 Configuration
 ──────────────────────────────────────────────────────────────────────────────
  ┌──────────────────────── Linux Module Utilities ─────────────────────────┐
  Arrow keys navigate the menu.  <Enter> selects submenus --->.  
  Highlighted letters are hotkeys.  Pressing <Y> includes, <N> excludes,  
  <M> modularizes features.  Press <Esc><Esc> to exit, <?> for Help, </>  
  for Search.  Legend: [*] built-in  [ ] excluded  <M> module  < >
 ┌─────────────────────────────────────────────────────────────────────┐  
 │[*] Simplified modutils  
 │[*] depmod (27 kb)                                                   │ │  
 │[*] insmod (22 kb)                                                   │ │  
 │[*] lsmod (1.9 kb)                                                   │ │  
 │[*] modinfo (24 kb)                                                  │ │  
 │[*] modprobe (28 kb)                                                 │ │  
 │[*] rmmod (3.3 kb)                                                   │ │  
 │--- Options common to multiple modutils  
 │[*] Accept module options on modprobe command line  
 │[*] Skip loading of already loaded modules  
(/lib/modules) Default directory containing modules  
(modules.dep) Default name of modules.dep  
 └─────────────────────────────────────────────────────────────────────┘  
  ├─────────────────────────────────────────────────────────────────────────┤  
                    <Select>    < Exit >    < Help >  
  └─────────────────────────────────────────────────────────────────────────┘

1.5 mdev 配置

shell
Busybox Configuration
	Linux System Utilities  ---> 
		[*] mdev (NEW) 
		[*]     Support subdirs/symlinks (NEW)                               
		[*]       Support regular expressions substitutions when renaming device (NEW)
		[*]     Support command execution at device addition/removal (NEW)
		[*]   Support loading of firmwares (NEW)

确保这几个选项是选中的(默认也是选中的)。

shell
 BusyBox 1.36.1 Configuration
 ──────────────────────────────────────────────────────────────────────────────
  ┌──────────────────────── Linux System Utilities ─────────────────────────┐
  Arrow keys navigate the menu.  <Enter> selects submenus --->.  
  Highlighted letters are hotkeys.  Pressing <Y> includes, <N> excludes,  
  <M> modularizes features.  Press <Esc><Esc> to exit, <?> for Help, </>  
  for Search.  Legend: [*] built-in  [ ] excluded  <M> module  < >
 ┌↑(-)─────────────────────────────────────────────────────────────────┐  
 │[*] lsusb (4.2 kb)                                                   │ │  
 │[*] mdev (17 kb)                                                     │ │  
 │[*]   Support /etc/mdev.conf  
 │[*]     Support subdirs/symlinks  
 │[*]       Support regular expressions substitutions when renaming dev│  
 │[*]     Support command execution at device addition/removal  
 │[*]   Support loading of firmware  
 │[*]   Support daemon mode  
 │[*] mesg (1.4 kb)                                                    │ │  
 │[*]   Enable writing to tty only by group, not by everybody  
 └↓(+)─────────────────────────────────────────────────────────────────┘  
  ├─────────────────────────────────────────────────────────────────────────┤  
                    <Select>    < Exit >    < Help >  
  └─────────────────────────────────────────────────────────────────────────┘

2. 编译 busybox

上一步配置完成就可以开始编译 busybox 了,我们可以执行如下命令:

shell
make

这个比较简单,只需要一个 make 命令就可以开始编译了,这是因为我们在图形配置界面中已经配置了交叉编译器了。一般问题不大,编译完成后会在源码的顶层目录下生成一个 busybox 文件:

image-20241128223035027

3. 安装 busybox

上一步只是进行了编译,我们还需要安装 busybox ,我们在终端执行:

shell
make install # 默认会安装到 _install 中
# 其实我们也可以直接指定安装的目录,避免后边拷贝相关文件的麻烦
make install CONFIG_PREFIX=/home/hk/4nfs/imx6ull_rootfs

安装完成后会有如下提示信息(也可能没有,但不重要,只要不报错就可以了):

image-20241128223103351

若未指定安装的目录,我们会发现在 busybox 源码顶层目录下会生成一个 _install 目录,我们看一下这个目录中都有什么:

shell
ls -alh _install

我们会发现有如下文件:

image-20241128223220820

这里边就是我们所需要的根文件系统,包含了根文件系统中所需的 shell 命令文件。

4. 添加 lib 库

4.1 拷贝 lib 库

我们还需要将交叉编译工具链中的库文件拷贝到 _install 目录下,我们先进入 _install 目录下,新建一个 lib 目录:

shell
cd _install/
mkdir lib

lib 文件夹创建好了,库文件从哪里来呢? lib 库文件从交叉编译器中获取。交叉编译器里面有很多的库文件,这些库文件具体是做什么的作为初学者得我肯定不知道,既然不知道那就把所有的库文件都放到我们的根文件系统中,这就意味着这样做出来的根文件系统肯定很大,但是我们现在是学习阶段,还做不了裁剪,所以这就意味着我们的 eMMC 需要比较大才会够用啦。

  • 交叉编译器的 arm-linux-gnueabihf/libc/lib 目录

我们进入交叉编译器目录拷贝相关文件:

shell
cd /home/sumu/2software/gcc-arm-linux-gnueabihf-8.3.0/arm-linux-gnueabihf/libc/lib # 我是放在这里的
cp -d *so* *.a ~/7Linux/busybox-1.36.1/_install/lib

拷贝完成后,根文件系统目录中的 lib 目录中的文件如下:

image-20241128223734254

注意 cp 命令后面的“-d”选项表示拷贝符号链接,这里有个比较特殊的库文件: ld-linux-armhf.so.3,此库文件也是个符号链接,它会链接到库 ld-2.28.so 上,输入以下命令查看此文件详细信息

shell
sumu@sumu-virtual-machine:~/7Linux/busybox-1.36.1/_install/lib$ ls ld-linux-armhf.so.3 -l
lrwxrwxrwx 1 sumu sumu 10 11月 28 22:36 ld-linux-armhf.so.3 -> ld-2.28.so
image-20241128223818603

ld-linux-armhf.so.3 后面有个“→”,表示其是个软连接文件,链接到文件 ld-2.28.so,因为其是一个“快捷方式”,因此大小显示为 0。但是, ld-linuxarmhf.so.3 不能作为符号链接,否则的话在根文件系统中执行程序无法执行。所以我们需要将实际的文件拷贝过来,方法很简单,那就是重新复制 ld-linuxarmhf.so.3,只是不复制软链接即可命令如下:

shell
cd ~/7Linux/busybox-1.36.1/_install/lib

# 删除 busybox-1.36.1/_install/lib 中的 ld-linux-armhf.so.3
rm ld-linux-armhf.so.3

# 重新拷贝文件
cd /home/sumu/2software/gcc-arm-linux-gnueabihf-8.3.0/arm-linux-gnueabihf/libc/lib
cp ld-linux-armhf.so.3 ~/7Linux/busybox-1.36.1/_install/lib

# 查看 busybox-1.36.1/_install/lib 中的 ld-linux-armhf.so.3 中的文件
cd ~/7Linux/busybox-1.36.1/_install/lib
ls ld-linux-armhf.so.3 -alh

重新拷贝后,结果如下:

image-20241128224116681
  • 交叉编译器的 arm-linux-gnueabihf/lib
shell
cd /home/sumu/2software/gcc-arm-linux-gnueabihf-8.3.0/arm-linux-gnueabihf/lib
cp *so* *.a ~/7Linux/busybox-1.36.1/_install/lib -d

最终我们得到的 lib 中的文件如下:

image-20241128224315501

4.2 向 /usr/lib 添加库

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

shell
cd /home/sumu/2software/gcc-arm-linux-gnueabihf-8.3.0/arm-linux-gnueabihf/libc/usr/lib
mkdir -p ~/7Linux/busybox-1.36.1/_install/usr/lib
cp *so* *.a ~/7Linux/busybox-1.36.1/_install/usr/lib -d

完成后的 busybox-1.36.1/_install/usr/lib 目录如下:

image-20241128224659107

4.3 查看库大小

目前我们的库已经添加完毕了,可以使用“du”命令来查看一下 busybox-1.36.1/_install/lib 和 busybox-1.36.1/_install/usr/lib 这两个目录的大小,命令如下:

shell
du ./lib ./usr/lib -sh
image-20241128224736311

可以看出 lib 和 usr/lib 这两个文件的大小分别为 151MB 和 91MB,加起来就是 242MB。

5. 创建其他目录

在根文件系统中还需要创建其他文件夹,如 dev 、 proc 、 mnt 、 sys 、 tmp 和 root 等:

shell
cd _install/
mkdir dev mnt proc root sys tmp var

创建完成后,我们的根文件系统目录如下图所示:

image-20241128224830214

我们刚才创建的几个都是空目录,其实可以发现我们还是少了一个 etc 目录,我们这里先不创建,一会先进行测试看看没有这个目录会有什么事情发生。

二、根文件系统初步测试

1. 拷贝根文件系统

我们这里将开发板设置为从 nfs 挂载根文件系统,我们需要先复制根文件系统到 nfs 目录下:

shell
cd ~/7Linux/busybox-1.36.1/_install
sudo cp -rf * ~/4nfs/imx6ull_rootfs

2. 设置 bootargs

shell
=> setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.10.101:/home/hk/4nfs/imx6ull_rootfs,proto=tcp rw ip=192.168.10.102:192.168.10.101:192.168.10.1:255.255.255.0::eth0:off init=/linuxrc'
=> saveenv

3. 重启开发板测试

注意我们使用的 uboot 参数与是从 tftp 加载 linux 内核和设备树(前边已经学习过了,有相关的笔记),从 nfs 挂载根文件系统。

image-20241128225304910

从图中我们会发现,根文件系统正常挂载了,并且 ls 命令也可正常运行,但是有一个错误提示:

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

这个错误提示其实很简单,说是无法运行“ /etc/init.d/rcS 这个文件,因为这个文件不存在。

三、完善根文件系统

1. 创建 /etc/init.d/rcS 文件

首先我们需要在 nfs 共享目录的根文件系统中创建一个 /etc 目录。rcS 是个 shell 脚本, Linux 内核启动以后需要启动一些服务,而 rcS 就是规定启动哪些文件的脚本文件。该文件应改位于 etc/init.d/rcS 文件,我们创建相关目录和文件:

shell
cd ~/7Linux/busybox-1.36.1/_install
mkdir -p etc/init.d
vim etc/init.d/rcS

这个文件并添加以下内容:

shell
#!/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
  • 第 1 行:表示这是一个 shell 脚本。
  • 第 3 行:PATH 环境变量保存着可执行文件可能存在的目录,这样我们在执行一些命令或者可执行文件的时候就不会提示找不到文件这样的错误。
  • 第 4 行:LD_LIBRARY_PATH 环境变量保存着库文件所在的目录 。
  • 第 5 行:使用 export 来导出上面这些环境变量,相当于声明一些“全局变量”。
  • 第 7 行:使用 mount 命令来挂载所有的文件系统,这些文件系统由文件 etc/fstab 来指定。
  • 第 8 和 9 行:创建目录/dev/pts,然后将 devpts 挂载到/dev/pts 目录中。
  • 第 11 行和第 12 行:使用 mdev 来管理热插拔设备,通过这两行, Linux 内核就可以在 /dev 目录下自动创建设备节点。关于 mdev 的详细内容可以参考 busybox 中的 docs/mdev.txt 文档。

说明

(1)这只是我们自己做的根文件系统中的 rcS 文件,这个是比较简单的,只有这么几行,但是 Ubuntu 或者其他大型 Linux 操作系统中的 rcS 文件,会更加的复杂,一般来说复杂的 rcS 文件也是借助其他工具创建的,比如 buildroot 等。

(2) etc/init.d/rcS 这个文件是 需要有可执行文件才可以运行的

shell
chmod 777 rcS

2. 创建 /etc/fstab 文件

2.1 格式说明

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

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

参数说明

  • file system :要挂载的特殊的设备,也可以是块设备,比如 /dev/sda 等等。
  • mount point :挂载点。
  • type :文件系统类型,比如 ext2 、 ext3 、 proc 、 romfs 、 tmpfs 等等。
  • ptions :挂载选项,在 Ubuntu 中输入 man mount 命令可以查看具体的选项。一般使用 defaults ,也就是默认选项, defaults 包含了 rw 、suid 、dev 、exec 、auto 、nouser 和 async 。
  • dump :为 1 的话表示允许备份,为 0 不备份,一般不备份,因此设置为 0 。
  • pass :磁盘检查设置,为 0 表示不检查。根目录 / 设置为 1 ,其他的都不能设置为 1 ,其他的分区从 2 开始。一般不在 fstab 中挂载根目录,因此这里一般设置为 0 。

2.2 创建文件

shell
cd ~/7Linux/busybox-1.36.1/_install
vim etc/fstab

我们创建好后添加以下内容:

shell
#<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

3. 创建 /etc/inittab 文件

3.1 格式说明

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

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

参数说明

  • id :每个指令的标识符,不能重复。但是对于 busybox 的 init 来说, id 有着特殊意义。对于 busybox 而言 id 用来指定启动进程的控制 tty ,一般我们将串口或者 LCD 屏幕设置为控制 tty 。
  • runlevels :对 busybox 来说此项完全没用,所以可以空着。
  • action :动作,用于指定 process 可能用到的动作。
动作 描述
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 :具体的动作,比如程序、脚本或命令等。

3.2 创建文件

shell
cd ~/7Linux/busybox-1.36.1/_install
vim etc/inittab

我们创建好文件后添加以下内容:

shell
#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。并且系统启动以后,在运行 process 之前在控制台上显示提示信息,只有用户按下 Enter 键以后才会执行 process 。
  • 第 4 行:启的话运行/sbin/init。
  • 第 5 行:按下 ctrl+alt+del 组合键的话就运行/sbin/reboot,所以 ctrl+alt+del 组合键用于重启系统。
  • 第 6 行:关机的时候执行/bin/umount,也就是卸载各个文件系统。
  • 第 7 行:关机的时候执行/sbin/swapoff,也就是关闭交换分区。

4. 根文件系统测试

我们直接在 nfs 共享目录中添加的相关文件,所以直接重启开发板就好啦。这一次就不会再有上边的哪个报错信息啦:

image-20241128230343427

四、根文件系统的优化

1. busybox 中文字符支持

1.1 中文乱码?

我们是通过 nfs 挂载的根文件系统,我们可以在 ubuntu 的相关目录下创建一个中文命名的目录,例如:

shell
cd /home/sumu/4nfs/imx6ull_rootfs
sudo mkdir 桌面
ls

然后我们会看到 ubuntu 下目录详情如下:

image-20241128230512790

然而我们到 MobaXterm 中的串口终端,看一下根目录:

image-20241128230452953

我们会发现并不支持中文而中中文目录显示为 ? 。老版本的 busybox 是支持中文的,但是不知道从哪个版本开始 busybox 中的 shell 命令对中文输入即显示做了限制,即使内核支持中文但在 shell 下也依然无法正确显示。这个时候就需要修改 busybox 源码了。我们先进入 busybox 源码顶层目录:

shell
cd ~/7Linux/busybox-1.36.1

1.2 printable_string.c 文件修改

首先我们需要修改 printable_string.c « libbb 文件,我们打开该文件后,会发现这里边只有一个 printable_string 函数,该函数中有这么几条语句:

c
const char* FAST_FUNC printable_string2(uni_stat_t *stats, const char *str)
{
	//...
	while (1) {
		//...
		if (c < ' ')
			break;
		if (c >= 0x7f) // (1)
			break;
		s++;
	}

#if ENABLE_UNICODE_SUPPORT
	dst = unicode_conv_to_printable(stats, str);
#else
	{
		char *d = dst = xstrdup(str);
		while (1) {
			//...
			if (c < ' ' || c >= 0x7f) // (2)
				*d = '?';
			d++;
		}
		//...
	}
#endif
	return auto_string(dst);
}

通过这几个语句我们知道,当字符大于 0X7F 以后就跳出去了。如果支持 UNICODE 码的话,当字符大于 0X7F 就直接输出 ? 。我们将上边的两个 if 语句进行修改:

c
/* 下边 if 出现在 34 行(将这个 if 注释掉) */
		// if (c >= 0x7f) // (1)
		// 	break;
/* 下边 if 出现在 48 行 */
			// if (c < ' ' || c > = 0x7f) // (2)
			if (c < ' ')
				*d = '?';

这两处修改主要是为了禁止字符大于 0X7F 以后 break 和输出 ? 。

1.3 unicode.c 文件修改

我们打开 unicode.c « libbb 文件,然后找到 unicode_conv_to_printable2 函数,在该函数中有这么几行:

c
static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t *stats, const char *src, unsigned width, int flags)
{
	//...
	if (unicode_status != UNICODE_ON) {
		char *d;
		if (flags & UNI_FLAG_PAD) {
			d = dst = xmalloc(width + 1);
			while ((int)--width >= 0) {
				//...
				*d++ = (c >= ' ' && c < 0x7f) ? c : '?'; // (1)
				src++;
			}
			*d = '\0';
		} else {
			d = dst = xstrndup(src, width);
			while (*d) {
				unsigned char c = *d;
				if (c < ' ' || c >= 0x7f) // (2)
					*d = '?';
				d++;
			}
		}
		//...
	}
	//...
	return dst;
}

1030 行表示当字符大于 0X7F 以后, *d++ 就为 ? , 1038 行和 1039 行表示,当字符大于 0X7F 以后,*d 也为 ? 。我们将其修改为以下内容:

c
/* 下边的这个三目运算符语句出现在 1030 行*/
				// *d++ = (c >= ' ' && c < 0x7f) ? c : '?'; // (1)
				*d++ = (c >= ' ') ? c : '?';
/* 下边的这个 if 出现在 1038 行*/
				// if (c < ' ' || c > = 0x7f) // (2)
				if (c < ' ')
					*d = '?';

1.4 busybox 配置

我们执行以下命令打开 busybox 的图形配置界面:

shell
make menuconfig

然后我们需要使能 busybox 的 unicode 编码以支持中文,配置路径如下:

shell
Busybox Configuration
    Busybox Settings  --->
            General Configuration  ---> 
                [*] Support Unicode
                [*]   Check $LC_ALL, $LC_CTYPE and $LANG environment variables

然后退出,一定要记得保存。

1.5 重新制作根文件系统

按照前边的步骤重新制作根文件系统即可。

1.6 中文支持测试

还是之前的样子,在根文件系统新建一个卓面目录,再来看一看串口终端的情况:

image-20241129102142162

2. 终端路径支持

image-20241128230912237

上边的图是 busybox 生成的根文件系统默认的情况,可以做成下图这样吗?

image-20241128230943361

2.1 PS1 变量介绍

PS1 命令是 linux 系统中的一个全局变量,用于定义用户命令行的字符显示。

我们看一下开发板中的 PS1 变量:

image-20230802210316413

我们再看一下 ubuntu 中的 PS1 变量:

image-20241128231105151

看到这里,是不是就有想法了呢?我们改变这个环境变量的值不就好了吗?或者直接把 ubuntu 中的复制过来就可以了嘛。

2.2 PS1 变量说明

我们以 ubuntu 中的 PS1 的值为例,简单了解一下都是什么意思。

2.2.1 内置变量
shell
\d :# 代表日期,格式为 weekday month date,例如:"Mon Aug 1"   
\H :# 完整的主机名称。   
\h :# 仅取主机的第一个名字。 
\t :# 显示时间为 24 小时格式,如:HH:MM:SS   
\T :# 显示时间为 12 小时格式   
\A :# 显示时间为 24 小时格式:HH:MM   
\u :# 当前用户的账号名称   
\v :# BASH 的版本信息   
\w :# 完整的工作目录名称。家目录会以 ~代替   
\W :# 利用 basename 取得工作目录名称,所以只会列出最后一个目录 
\# :# 下达的第几个命令   
\$ :# 提示字符,如果是 root 时,提示符为:# ,普通用户则为:$
2.2.2 颜色设置

颜色代码格式:\[\e[F;Bm\](其中 F 表示字体颜色,B 表示背景颜色,其实 e 也可以用 033):

字体代码背景代码颜色
3040黑色
3141红色
3242绿色
3343黄色
3444蓝色
3545紫红色
3646青蓝色
3747白色

其实这里的语法格式跟 printf 还有 echo 的颜色输出是一样的,都是使用的 ANSI 控制码。

2.3 PS1 变量修改

我们在根文件系统的 /etc 目录中新建一个 profile 文件,输入以下内容:

shell
#!/bin/sh
export HOSTNAME=imx
export root=root
export PS1="\[\e[36;1m$root@$HOSTNAME\e[0m: \e[34;1m\w\e[0m\]\$ "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH

然后重启系统,我们会看到以下情况:

image-20241128231245341

【注意】 PS1 变量修改的时候注意在命令提示符后边需要多加一个空格。