BusyBox 构建根文件系统

Linux根文件系统结构

在这里插入图片描述
etc下存在的配置文件:

文件描述
export用来配置NFS文件系统(可选)
fstab用来指明当执行mount -a时需要挂载的文件系统(可选)
mtab用来显示已经加载的文件系统(可选)
ftpusers启动FTP时配置用户访问权限(可选)
group用来配置NFS文件系统(可选)
inittabinit进程配置文件(可选)
ld.so.conf其他共享库的路径(可选)
passwd密码文件(可选)

系统启动后,使用以下命令挂接proc文件系统(常在/etc/fstab进行设置以自动挂接)

 mount -t proc none /proc

一些需要生成临时文件的程序要用到/tmp目录,所 以/tmp目录必须存在并可以访问。
为减少对Flash的操作,当在/tmp目录上挂接内存文件系统 :

mount -t tmpfs none /tmp

BusyBox源码下载

BusyBox


制作BusyBox根文件系统

所谓制作根文件系统,就是创建各种目录,并且在里面创建各种文件。比如在/bin、/sbin目录下存放各种可执行程序,在/etc目录下存放配置文件,在/lib目录下存放库文件。这节讲述如何使用Busybox来创建/bin、/sbin等目录下的可执行文件。

创建根文件系统存放目录:

cd nfs
mkdir rootfs

开发中一般nfs挂载进行测试文件系统,所以将目录建立在nfs下

直接修改根目录下的Makefile,防止查找编译工具链出错:

VERSION = 1
PATCHLEVEL = 29
SUBLEVEL = 0
EXTRAVERSION =
NAME = Unnamed

ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm-gcc/gcc-linaro-4.9.4-2017.01-i686_arm-linux-gnue$

测试发现在make编译添加ARCH和CROSS_COMPILE的定义还是编译出问题,编译成了x86架构的,所以这里直接修改Makefile直接定义ARCH和CROSS_COMPILE。

编译安装参考源码的INSTALL文件:

Building:
=========

The BusyBox build process is similar to the Linux kernel build:

  make menuconfig     # This creates a file called ".config"
  make                # This creates the "busybox" executable
  make install        # or make CONFIG_PREFIX=/path/from/root install

The full list of configuration and install options is available by typing:

  make help

...
...


修改busybox支持中文字符:libbb/printable_string.c、libbb/unicode.c

修改printable_string.cprintable_string函数,将以下语句

  /* 汉字字符肯定大于0x7F,当字符大于 0X7F 以后就跳出去了,不进行操作 */
if (c >= 0x7f)  
    break;
 /* 汉字字符肯定大于0x7F,如果支持 UNICODE 码的话,当字符大于 0X7F 就直接输出‘?’,汉字必定显示不了*/
 if (c < ' ' || c >= 0x7f) 
        *d = '?';

改成如下


 /* 当字符大于 0X7F 以后就跳出去了,注释掉该语句即可 */
    /* if (c >= 0x7f)   
          break;   */

 /* 如果支持 UNICODE 码的话,当字符大于 0X7F 就直接输出‘?’,那改成大于0x7F还输出即可 */
    /* if (c < ' ' || c >= 0x7f) */ 
    if (c < ' ')
         *d = '?';
 

从代码看会发现,如果字符大于0x7f就会跳出循环停止操作以及如果支持UNICODE编码,字符大于0x7f就会输出’?',汉字字符肯定大于0x7F,所以汉字必定不会显示

修改unicode.cunicode_conv_to_printable2函数,将以下语句

 *d++ = (c >= ' ' && c < 0x7f) ? c : '?';

  if (c < ' ' || c >= 0x7f)
        *d = '?';

改成如下

 *d++ = (c >= ' ') ? c : '?';

  if (c < ' ')
        *d = '?';

编译前也需要配置busybox :三种配置项

  1. defconfig, 默认配置
  2. allyesconfig,全选配置,即选中BusyBox所有功能
  3. allnoconfig,最小配置

一般使用默认配置即可。

 make defconfig
	
make menuconfig     /* BusyBox也支持图形化配置 */

需要取消或设置的一些选项:

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

取消Build static binary (no shared libs)静态编译,默认是不选中的。动态编译出来的库会静态编译的小
采用静态编译的 DNS 会出问题,无法进行域名解析

勾选vi-style line editing commands

Settings  ---> 
	[ ] vi-style line editing commands 

启用vi样式的行编辑。 在shell中,该模式可以是用“set -o vi”和“set +o vi”打开或关闭功能。

取消Simplified modutils

Linux Module Utilities  ---> 
	[*] Simplified modutils

Simplified modutils默认会选中,需要取消

确保 mdev选项以及其子选项被选中

Linux System Utilities  --->
	[*] mdev (16 kb)                                                                                           
         [*] Support /etc/mdev.conf                                                                               
              [*] Support subdirs/symlinks                                                                           
                  [*] Support regular expressions substitutions when renaming device                            
              [*] Support command execution at device addition/removal                                                
         [*] Support loading of firmware

默认都是被选中的。

使能unicode 编码支持,确保选中 Support UnicodeCheck $LC_ALL, $LC_CTYPE and $LANG environment variables

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

Support Unicode默认是选中。

其他配置选项根据需要进行配置。

编译:

ares@ubuntu:~/nfs/rootfs/busybox-1.29.1$ cat build_busybox.sh 
#!/bin/bash

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8

安装:

ares@ubuntu:~/nfs/rootfs/busybox-1.29.1$ cat install_busybox.sh 
#!/bin/bash

make install CONFIG_PREFIX=/home/ares/nfs/rootfs
aares@ubuntu:~/nfs/rootfs$ ls
bin  linuxrc  sbin  usr

binlinuxrcsbin以及usr是安装后生成的内容
若uboot的环境变量bootargs 设置 init=/linuxrc,则linuxrc可以作为用户空间的init程序

用户态空间的 init 程序是 busybox 来生成的

向rootfs添加lib库

linux应用程序运行需要动态库或静态库,从安装生成目录来看,显然没有库文件,负责编译好的应用程序放到系统中也无法运行。所以要添加库文件。

在ubuntu下一般使用/lib和/usr/lib存放库文件。

创建lib和usr/lib

ares@ubuntu:~/nfs/rootfs$ mkdir lib
ares@ubuntu:~/nfs/rootfs$ ls
bin  lib  linuxrc  sbin  usr

ares@ubuntu:~/nfs/rootfs/usr$ mkdir lib
ares@ubuntu:~/nfs/rootfs/usr$ ls
bin  lib  sbin

拷贝库文件到rootfs中

ares@ubuntu:/usr/local/arm_gcc/gcc-linaro-4.9.4-2017.01-i686_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib$ sudo cp *so* *.a /home/ares/nfs/rootfs/lib/ -d
  • -d,表示保留链接文件属性
ares@ubuntu:/usr/local/arm_gcc/gcc-linaro-4.9.4-2017.01-i686_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib$ sudo cp *so* *.a /home/ares/nfs/rootfs/usr/lib/ -d

这些库文件中有个特殊文件:

guangjie@ubuntu:/usr/local/arm-gcc/gcc-linaro-4.9.4-2017.01-i686_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib$ ls ld-linux-armhf.so.3 -l
lrwxrwxrwx 1 11827 9000 24 Feb  1  2017 ld-linux-armhf.so.3 -> ld-2.19-2014.08-1-git.so
  • ld-linux-armhf.so.3 ,是链接文件

上面复制的库文件并不是每个都会用到,可以根据应用程序的依赖关系保留需要用到的,以此来减小rootfs的空间占用。
通过ldd命令可以查看应用程序依赖关系,但主机的ldd命令架构和嵌入式的架构一般不同,无法查看。

guangjie@ubuntu:~/nfs/rootfs$ ldd hello
        linux-vdso.so.1 (0x00007ffeacad9000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5265cd1000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f52662c4000)

嵌入式平台查看依赖关系方法

arm-linux-gnueabihf-readelf -a "your binary" | grep "Shared"

guangjie@ubuntu:~/nfs/rootfs$ arm-linux-gnueabihf-readelf -a hello | grep "Shared"
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]

查看库大小

ares@ubuntu:~/nfs/rootfs$ du ./lib/ ./usr/lib/ -sh
57M     ./lib/
67M     ./usr/lib/

创建目录

busybox编译后安装已经生成bin、sbin、usr三个目录。需要手动添加其他目录。
如dev、proc、mnt、sys、tmp 、root等

打包

sudo tar -vcjf busybox_rootfs.tar.bz2 *

初步测试

启动信息:

VFS: Mounted root (ext3 filesystem) on device 179:2.
devtmpfs: mounted
Freeing unused kernel memory: 400K (8090e000 - 80972000)
hub 1-1:1.0: USB hub found
hub 1-1:1.0: 2 ports detected
can't run '/etc/init.d/rcS': No such file or directory

Please press Enter to activate this console.
/ # ls
bin         hello       linuxrc     proc        sys
dev         hello.c     lost+found  root        tmp
driver      lib         mnt         sbin        us

can't run '/etc/init.d/rcS': No such file or directory可以看出文件系统还存在问题。


完善rootfs

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

rcS是个shell脚本文件,可以在其中指定linux启动后需要自动启动的服务

创建脚本/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   #  mount 命令来挂载所有的文件系统 文件系统由文件/etc/fstab
mkdir /dev/pts # 创建目录/dev/pts
mount -t devpts devpts /dev/pts # 将 devpts 挂载到/dev/pts 目录

echo /sbin/mdev > /proc/sys/kernel/hotplug   # 使用mdev来管理热插拔设备,使可以自动创建设备节点
mdev -s   #使用 mdev 来管理热插拔设备

赋予脚本可执行权限

sudo chmod 777 rcS

创建/etc/fstab 文件

格式

[file system>   [mount point]  [type]  [options]  [dump]   [pass] 
  • [file system] 要挂载的特殊的设备,也可以是块设备
  • [mount point] , 挂载点
  • [type] 文件系统类型,比如 ext2、ext3、proc、romfs、tmpfs 等
  • [options] 挂载选项,主机man mount可以查看挂载选项
  • [dump],为 1 的话表示允许备份,为 0 不备份,一般不备份,因此设置为 0
  • [pass],磁盘检查设置, 0 表示不检查。根目录‘/’设置为 1,其他的都不能设置为 1,其他的分区从 2 开始。一般不在 fstab 中挂载根目录,故一般设置为 0

创建/etc/fstab 文件

proc              /proc             proc        defaults    0        0
tmpfs             /tmp              tmpfs       defaults    0        0
sysfs             /sys              sysfs       defaults    0        0

创建/etc/inittab 文件

格式:

[id]:[runlevels]:[action]:[process] 
  • [id],每个指令的标识符,不能重复。对于 busybox 的 init 来说,id有着特殊意义,一般用来指定启动进程的控制 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 重启的时候才会执行 process
ctrlaltdel当按下 ctrl+alt+del 组合键才会执行 process
shutdown关机的时候执行 process
  • [process] ,具体的动作,比如程序、脚本或命令

参考 busybox 的 examples/inittab 文件,创建自己的inittab文件:

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

测试根文件系统

执行测试程序:


/ # ./hello
hello world

创建中文文件:

/ # touch 网盘aig挤干净i宁、.txt
/ #
/ #
/ # ls
bin                            lost+found
busybox_rootfs.tar.bz2         mnt
dev                            proc
driver                         root
etc                            sbin
hello                          sys
hello.c                        tmp
lib                            usr
linuxrc                        网盘aig挤干净i宁、.txt
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欲盖弥彰1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值