Busybox快速构建根文件系统

1. busybox 下载

  busybox源码包官网下载     busybox官网开发者手册

Busybox快速构建根文件系统_第1张图片

下载完成后,解压得到如下图所示目录:

busybox 与 内核源码、u-boot源码配置类似,也存在默认配置,在configs目录下面,但因为其配置比较简单,一般没采用默认配置.(思考:如何添加自定义的配置到configs目录使其能make xx_defconfig)

$ make help  //可以查看make 实现哪些功能

Busybox快速构建根文件系统_第2张图片

2.  编译busybox

      指定ARCH  、CROSS_COMPILE  、SYSROOT

      示例: 

      $ export  ARCH = powerpc

      $ export CROSS_COMPILE = powerpc-fsl-linux-gnuspe-  

      若 没设置CROSS_COMPILE变量,则需要在Busybox Settings-->Build Options --> Cross Compiler prefix 填写 编译器的前缀

Busybox快速构建根文件系统_第3张图片

 关于SYSROOT

 CONFIG_SYSROOT:                                                                                                           |  
  |                                                                                                                           |  
  | If you want to build BusyBox with a cross compiler, then you                                                              |  
  | might also need to specify where /usr/include and /usr/lib                                                                |  
  | will be found.                                                                                                            |  
  |                                                                                                                           |  
  | For example, BusyBox can be built against an installed                                                                    |  
  | Android NDK, platform version 9, for ARM ABI with                                                                         |  
  |                                                                                                                           |  
  | CONFIG_SYSROOT=/opt/android-ndk/platforms/android-9/arch-arm                                                              |  
  |                                                                                                                           |  
  | Native builds leave this empty.                                                                                           |  
  |                                                                                                                           |  
  | Symbol: SYSROOT [=]                                                                                                       |  
  | Prompt: Path to sysroot                                                                                                   |  
  |   Defined at Config.in:632                                                                                                |  
  |   Location:                                                                                                               |  
  |     -> Busybox Settings                                                                                                   |  
  |       -> Build Options   

Busybox快速构建根文件系统_第4张图片

若使用交叉编译器不设置此选项,则可能出现如下问题

Busybox快速构建根文件系统_第5张图片

  以上基本配置完成后,make menuconfig 根据需要配置 (一般不用配置)

  需要注意的就几个点:

  1.BusyBox installation prefix 选项  ,执行make install时安装的目录,默认设置为当前源码目录的_install

  2.使用vi风格时 busybox setting->busybox library tuning下的下面两个开关打开。第一个是选择vi风格的命令行。

  3. 选中 Build BusyBox as a static binary 可以减少根文件系统空间 ,这样它自身不需使用动态库

Busybox快速构建根文件系统_第6张图片

  4.需要注意Linux Module Utilities 和 Linux System Utilities

  执行make 

Busybox快速构建根文件系统_第7张图片

执行make install

Busybox快速构建根文件系统_第8张图片

 

3. Linux踩坑启动生成的根文件系统

    设置uboot bootargs启动参数


bootargs=root=/dev/nfs nfsroot=192.168.1.141:/root/rootfs/ 
ip=192.168.16.88:192.168.16.106:192.168.16.1:255.255.255.0::eth1:off 
init=/linuxrc console=ttyS0,115200

 

Busybox快速构建根文件系统_第9张图片

此时会因为找不到/etc/init.d/rcS (第一个执行的脚本)  以及终端设备/dev/tty2等设备无法进入命令行

注意时,/etc/inittab是busybox第一个解析的配置文件,当找不到时会使用默认配置,所以当根文件系统缺少/etc/inittab时也不会出现 can't open /etc/inittab的信息。

下面开始一步一步补充根文件系统缺少的文件和目录

1.创建etc目录,新建inittab文件

 简单介绍inittab,详细后面博客补充

 inittab内容以行为单位,行与行之间没有关联,每行都是一个独立的配置项,每一个配置项表示一个独立的意思

 ::: 

id字段与通常的inittab中的含义不同,它代表的是这个语句中process执行所在的tty设备,内容就是/dev目录中tty设备的文件名。由于是运行process的tty设备的文件名,所以也不能像通常的inittab那样要求每条语句id的值唯一

busybox不支持runlevel(没具体分析过),所以此字段完全被忽略

runlevel也是一个shell变量,并且导出为环境变量

runlevel变量的作用:Linux操作系统自从开始启动至启动完毕需要经历几个不同的阶段,这几个阶段就叫做runlevel,同样,当linux操作系统关闭时也要经历另外几个不同的runlevel。设置runlevel,是为了linux系统避免不必要的重启动。

Linux系统有7个运行级别(runlevel)
运行级别0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启动
运行级别1:单用户工作状态,root权限,用于系统维护,禁止远程登陆
运行级别2:多用户状态(没有NFS)
运行级别3:完全的多用户状态(有NFS),登陆后进入控制台命令行模式
运行级别4:系统未使用,保留
运行级别5:X11控制台,登陆后进入图形GUI模式
运行级别6:系统正常关闭并重启,默认运行级别不能设为6,否则不能正常启动

S, s  Single user mode

    runlevel=s,表示将系统设置为单用户模式

sysinit, respawn, askfirst, wait,once, restart, ctrlaltdel, shutdown,initdefault 等(其它参考官网 man inittab介绍)

上面标红比较常用,需要注意的是:

askfirst,它的含义与respawn相同,只是在运行process前,会打出一句话 "please press Enter to active this console",然后等用户在终端上敲入回车键后才运行process。

sysinit :为init提供初始化命令行的路径 <一般在inittab为si::sysinit:/etc/init.d/rcS 表示执行/etc/int.d目录下rcS脚本>

si 是系统初始化的进程,该字段可以不写,当写si时,实践中出现了can't open /dev/si: No such file or directory,目前还不太清楚与什么有联系

下面为成熟的文件系统中的实现:

respawn:每当相应的进程终止执行便重新启动

wait: 告诉init必须等到相应的进程完成才能继续执行

shutdown:当系统关机时,执行相应的进程

restart:当init重新启动时,执行相应的进程。

once:仅执行相应的进程一次,而且不会等待它完成

ctrlaltdel:当按下Ctrl-Alt-Delete组合键时,执行相应的进程

#first: run the system script file
#控制台在启动之前,执行/etc/init.d/rcS程序
::sysinit:/etc/init.d/rcS
#控制台启动时,执行/bin/sh程序。若没有执行类似登录,则无法出现交互终端   
::askfirst:-/bin/sh
#按下ctrl+alt+del,执行/bin/reboot程序
::ctrlaltdel:-/bin/reboot
#关机时,执行/bin/umount程序,并传入两个参数, -a –r    
::shutdown:/bin/umount -a -r
#重启,执行/sbin/init程序
::restart:/sbin/init

再次启动根文件系统会出现can't run '/etc/init.d/rcS': No such file or directory

2.创建rcS文文件,且需要加入执行权限

再次启动,可以发现能基本出现交互终端

Busybox快速构建根文件系统_第10张图片

 3.继续深入的验证,思考下面问题

 1)如何让串口终端登录 以及登录时密码与账户如何验证的

     屏蔽/bin/sh ,加入ttyS0:12345:respawn:/sbin/getty -L 115200 ttyS0

     说明:一般情况下上面ttyS0应该只需要写S0,也就是tty的尾缀,但本文完成最终实验时,发现启动时若采用S0还是会出现

      can't open /dev/S0: No such file or directory,待分析成熟文件系统中如何实现的 

#first: run the system script file
#控制台在启动之前,执行/etc/init.d/rcS程序
::sysinit:/etc/init.d/rcS

#控制台启动时,执行/bin/sh程序。若没有执行类似登录,则无法出现交互终端   
#::askfirst:-/bin/sh
ttyS0:12345:respawn:/sbin/getty -L 115200 ttyS0

#按下ctrl+alt+del,执行/bin/reboot程序
::ctrlaltdel:-/bin/reboot

#关机时,执行/bin/umount程序,并传入两个参数, -a –r    
::shutdown:/bin/umount -a -r

#重启,执行/sbin/init程序
::restart:/sbin/init

完成上面后,启动时,也会出现can't open /dev/ttyS0: No such file or directory,这是因为系统此时还没有在/dev 创建对应的设备文件

 2)创建dev目录后,怎么让dev目录看见对应的设备

    现在系统大部分设备节点都是由mdev或者udev根据驱动实现自动创建的,所以只需要让脚本执行mdev或者udev相关的操作即可

此时在/etc/init.d/rcS中加入下面内容即可

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel

mount -a

echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

/bin/hostname -F /etc/hostname

上面分为4个部分:

(a)导出坏境变量 

        定义PATH变量,后面用export导出,那PATH就变成了环境变量。

        PATH环境变量是linux系统内部定义的一个环境变量,含义是操作系统去执行程序时会默认到PATH指定的各个目录下去寻找。如果找不到就认定这个程序不存在,如果找到了就去执行它。将一个可执行程序的目录导出到PATH,可以让我们不带路径来执行这个程序。

         rcS文件还没添加,系统启动就有了PATH的值?原因在于busybox自己用代码硬编码为我们导出了一些环境变量,其中就有PATH。

在busybox的init.c的init_main函数中,有以下几行代码,设置了几个环境变量,其中就有PATH。

/* Make sure environs is set to something sane */

putenv((char *) "HOME=/");

putenv((char *) bb_PATH_root_path);

putenv((char *) "SHELL=/bin/sh");

putenv((char *) "USER=root"); /* needed? why? */

在libbb.h中,有定义bb_PAYH_root_path,其实就是/bin /sbin /usr/bin /usr/sbin

extern const char bb_PATH_root_path[] ALIGN1; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */

(b)挂载根文件系统 mount -a

   mount命令是用来挂载文件系统的。

   mount –a是挂在所有的应该被挂载的文件系统,在busybox中mount –a时busybox会去查找一个文件/etc/fstab文件,这个文件按照一定的格式列出了所有应该被挂载的文件系统(包括了虚拟文件系统)格式统一的

# /etc/fstab: static file system information.
#
# Use 'vol_id --uuid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
#         
  proc          /proc        proc   defaults     0         0
  sysfs         /sys         sysfs  defaults     0         0
  tmpfs         /var         tmpfs  defaults     0         0
  tmpfs         /tmp         tmpfs  defaults     0         0
  tmpfs         /dev         tmpfs  defaults     0         0

需要注意的是,mdev/udev 需要挂载 tmpfs - /dev   proc-/proc  sysyfs - /sys 不然都无法成功创建设备

编辑完/etc/fstab后,还需手动创建proc  sys  dev 目录

下面为没挂载tmpfs到/dev时,出现的问题

Busybox快速构建根文件系统_第11张图片

(c) mdev

mdev是udev的嵌入式简化版本,udev/mdev是用来配合linux驱动工作的一个应用层的软件,udev/mdev的工作就是配合linux驱动生成相应的/dev目录下的设备文件。

本来,在dev目录下,是空目录。但是当rcS文件中,添加下面两行,配合上面的文件系统挂载,

echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

在dev目录下,就会生成很多设备文件。这些设备文件,就是mdev生成的。

Busybox快速构建根文件系统_第12张图片

配置完成后,串口登录时出现下面输入密码的提示,此时因为没有对应/etc/passwd,则无法登录

关于系统密码登录这块的介绍:

inux的账号验证程序是login,login会接收getty传来的用户名作为用户名参数。
然后login会对用户名进行分析:如果用户名不是root,且存在/etc/nologin文件,
login将输出nologin文件的内容,然后退出。这通常用来系统维护时防止非root用户登录。
只有/etc/securetty中登记了的终端才允许root用户登录,如果不存在这个文件,则root可以
在任何终端上登录。/etc/usertty文件用于对用户作出附加访问限制,如果不存在这个文件,则没有其他限制。

在分析完用户名后,login将搜索/etc/passwd以及/etc/shadow来验证密码以及设置账户的其它信息,
比如:主目录是什么、使用何种shell。如果没有指定主目录,将默认为根目录;如果没有指定shell,
将默认为/bin/bash。

login程序成功后,会向对应的终端在输出最近一次登录的信息(在/var/log/lastlog中有记录)
并检查用户是否有新邮件(在/usr/spool/mail/的对应用户名目录下)。
然后开始设置各种环境变量:
对于bash来说,系统首先寻找/etc/profile脚本文件,并执行它;然后如果用户的主目录中存在.bash_profile文件,
就执行它,在这些文件中又可能调用了其它配置文件,所有的配置文件执行后后,
各种环境变量也设好了,这时会出现大家熟悉的命令行提示符,到此整个启动过程就结束了。

 创建/etc/passwd文件,添加下面内容即可

root::0:0:root:/home/root:/bin/sh

Busybox快速构建根文件系统_第13张图片

当我换成root:x:0:0:root:/home/root:/bin/sh时,登录居然需要密码,后面待验证,感觉和busybox vi编辑模式相关

(d)hostname

    hostname是linux中的一个shell命令。命令(hostname xxx)执行后可以用来设置当前系统的主机名为xxx,直接hostname不加参数可以显示当前系统的主机名。

    设置了主机名,就可以在命令行中,显示主机名。

    没有设置主机名的时候,使用hostname命令,会打印当前的IP地址。

    新建/etc/hostname 且写入自定义的hostname

3)如何修改根文件系统的提示符

   请参考根文件系统的提示符

 

4. 参考文章

/etc/inittab文件详解

busybox根文件系统构建

 

 

 

 

 

 

 

 

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