BusyBox 构建根文件系统

Linux根文件系统结构

BusyBox 构建根文件系统_第1张图片
etc下存在的配置文件:

文件 描述
export 用来配置NFS文件系统(可选)
fstab 用来指明当执行mount -a时需要挂载的文件系统(可选)
mtab 用来显示已经加载的文件系统(可选)
ftpusers 启动FTP时配置用户访问权限(可选)
group 用来配置NFS文件系统(可选)
inittab init进程配置文件(可选)
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

你可能感兴趣的:(Linux文件系统,rootfs)