导读
命令是linux操作系统独特的艺术,虽然Windows操作系统也有命令,但相比之下,linux的命令更加强大且具有魅力。大多数桌面和嵌入式linux发行版都包含了很多功能完备的命令行工具,然而busybox短小精悍,可以替代这些工具,在资源有限的嵌入式linux系统中更具有优势。
busybox的使用
站在使用的角度,busybox的使用非常简单,如果配置和编译过linux内核,将会发现使用思路是一样的:
(1)获取busybox源码。
(2)在终端执行一个配置工具(可以使用
make menuconfig
编译出宿主机上的配置图形界面进行配置),如下图:

在工具中可以指定交叉编译器路径
、想要的命令
、busybox的支持特性
、安装路径
等配置。
对于busybox的配置有以下几种:1、defconfig,缺省配置,也是默认配置选项。2、allyesconfig,全选配置,也就是选中busybox的所有功能。3、allnoconfig,最小配置。在实际使用中,图形化配置方式是一种较常使用的方法。
(3)在终端运行
make
命令来构建busybox源码。(4)将编译出的二进制工具和一系列的符号链接安装到我们的目标系统中。(还需要将相关的动态链接库安装到对应的路径下,确保busybox下的程序能正常启动运行)。
通过以上步骤,就可以使用busybox了。
busybox的启动方式
在linux内核启动后期,会尝试执行/sbin/
、/etc
、/bin
三个目录中的init。在busybox下的init
运行后,首先则会提示busybox找到不/etc/init.d/rcS
文件(编译构建出的busybox本身是没有这个路径下的rcS文件的),这是busybox搜索的默认初始化脚本文件,我们则可以创建该文件,至于文件中写些什么内容,后文会描述到。
在busybox完成初始化后,会显示一条提示信息,要求我们按下回车键,以激活一个控制台。当busybox检测到回车键被按下后,则会执行一个ash(busybox的内置shell)会话,然后我们就可以在其中输入命令了,busybox会根据我们输入的命令执行对应的命令操作。
一般情况下,一个基于busybox构建的根文件系统,我们能够使用大约100多个工具,包括:核心工具、文件处理工具、网络工具和一个shell程序,基于这些工具,我们则可以构建自己的系统应用程序了。
rcS初始化脚本
在初始化一个基于busybox的嵌入式系统时,rcS初始化脚本是首选的方式。由于不同应用场景和需求,rcS启动脚本中的内容都会不一样:有的会创建目录、循环执行子目录中脚本文件(这种方式可以划分多个脚本文件,清晰明了,便于管理)、挂载文件系统、启动linux服务,启动相应的应用程序等,这里描述一个最简单的rcS脚本文件:
#!/bin/sh
mount -t proc /proc/proc
syslogd
klogd
ifconfig lo 127.0.0.1
xinetd
busybox sh
/bin/my_app
上述脚本中依次执行的操作是:
(1)挂载/proc
文件系统,挂载点是/proc目录。
(2)开启系统的日志程序,便于捕捉系统启动中出现的问题。
(3)开启系统日志守护程序。
(4)配置系统的本地回环接口。
(5)启动英特网超级服务器xinetd
。
(6)启动shell。
(7)启动运行我们自己设计的应用程序my_app
。
busybox重要文件
在busybox安装目录/etc
下,存在几个必须的基本文件和目录:

(1)inittab文件
/etc/inittab
文件中不同action类型有着先后顺序:
SYSINIT > WAIT > ONCE > RESPAWN | ASKFIRST
在busybox源码中,定义如下:
#define SYSINIT 0x01 //最先开始启动,并且执行完毕后才会进入WAIT。
#define WAIT 0x02 //在SYSINIT之后启动,并且执行完毕后才会启动ONCE。
#define ONCE 0x04 //在WAIT之后启动,但是后面的并不需要等待执行完毕。
#define RESPAWN 0x08 //在ONCE之后启动,退出后会重新启动。
#define ASKFIRST 0x10 //类似RESPAWN,但是需要<Enter>确认。
#define CTRLALTDEL 0x20 //收到SIGINIT后执行,并且执行完毕后开始执行RESPAWN和ASKFIRST。
#define SHUTDOWN 0x40 //在kill所有进程之后启动SHUTDOWN。这是为RESTART或者底层halt/reboot/poweroff做准备。
#define RESTART 0x80 //收到SIGQUIT后执行RESTART。
在busybox的init程序中,会读取/etc/inittab文件,该文件中的内容由若干条指令组成,每条指令的结构都是一样的,以“:”分隔的4个字段组成,格式如下:
<id>:<runlevels>:<action>:<process>
- id:每个指令的标识符,不能重复。但是对于 busybox 的 init 来说, <id>有着特殊意义。对于busybox而言<id>用于指定启动进程的控制tty,一般我们将串口或者LCD屏幕设置为控制tty。
- runlevels:对 busybox 来说此项完全没用,所以空着。
- action:表示动作,用于指定可能用到的动作。busybox 支持的动作如下图所示:

- process:表示具体的动作操作,比如程序、脚本或命令等。
例如下图所示的配置选择:

(2)fstab文件
fstab文件用于指定在linux启动以后自动配置哪些需要自动挂载的分区,文件中内容格式如下:
<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。
例如下列的配置选择:

(3)profile文件
该文件不是必须的,该文件是shell读取的配置文件。profile
脚本文件是传递给ash程序的,在ash程序中会读取profile文件中的内容,作为环境变量的参数配置。例如下列配置选择:

上述配置脚本中,首先设置PATH
、PS1
环境变量,PS1变量表示:我们在使用命令行时的命令提示符的格式,每一次按下回车后系统都会调用PS1变量,产生新的命令提示符等待输入。然后设置了PAGER
、EDITOR
环境变量。接着,循环执行/etc/profile.d/
目录下的所有的shell脚本。
(4)passwd文件
passwd文件由多条记录组成,例如如下的内容:
root:x:0:0:root:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/false
bin:x:2:2:bin:/bin:/bin/false
sys:x:3:3:sys:/dev:/bin/false
sync:x:4:100:sync:/bin:/bin/sync
mail:x:8:8:mail:/var/spool/mail:/bin/false
www-data:x:33:33:www-data:/var/www:/bin/false
operator:x:37:37:Operator:/var:/bin/false
nobody:x:65534:65534:nobody:/home:/bin/false
dbus:x:1000:1000:DBus messagebus user:/var/run/dbus:/bin/false
systemd-bus-proxy:x:1001:1005:Proxy D-Bus messages to/from a bus:/:/bin/false
systemd-journal-gateway:x:1002:1006:Journal Gateway:/var/log/journal:/bin/false
systemd-journal-remote:x:1003:1007:Journal Remote:/var/log/journal/remote:/bin/false
systemd-journal-upload:x:1004:1008:Journal Upload:/:/bin/false
systemd-network:x:1005:1009:Network Manager:/:/bin/false
systemd-resolve:x:1006:1010:Network Name Resolution Manager:/:/bin/false
systemd-timesync:x:1007:1011:Network Time Synchronization:/:/bin/false
(注:不同linux系统环境,在文件中的内容可能会不一样。)
每条记录占一行,记录了一个账号的所有相关信息,单条记录由7个字段组成,每个字段之间用“:”隔开,其格式如下:
username:password:UID:GID:connection:home dictionary:shell
『字段含义』
username:用户名
它唯一地标识了一个用户帐号,用户在登录时使用的就是它。
password:该账户的口令
passwd文件中存放的密码是经过加密处理的。Linux的加密算法很严密,其中的口令几乎是不可能被破解的。
User ID用户识别码,简称UID
Linux系统内部使用UID来标识用户,而不是用户名。UID是一个整数,用户的UID互不相同。0是系统管理员账号,1-499是系统保留账号,500+即一般账号。
Group ID用户组识别码,简称GID
不同的用户可以属于同一个用户组,享有该用户组共有的权限。与UID类似,GID唯一地标识了一个用户组。用usermod -g 设置。
comment 这是给用户帐号做的注解
它一般是用户真实姓名、电话号码、住址等,当然也可以是空的。
home directory 主目录
这个目录属于该帐号,当用户登录后,它就会被置于此目录中,就像回到家一样。一般来说,root帐号的主目录是/root,其他帐号的家目录都在/home目录下,并且和用户名同名。用usermod -d设置。
login command 用户登录后执行的命令
一般来说,这个命令将启动一个shell程序。例如,用bbs帐号登录后,会直接进入bbs系统,这是因为bbs帐号的login command指向的是bbs程序,等系统登录到bbs时就自动运行这些命令。
总结
本文是小生分析busybox源码的最后一篇,描述了经busybox构建完成后的最小根文件系统中需要添加哪些文件以及文件的解析过程。
从使用者的角度来看,能够编译构建busybox,能够填充最小的根文件系统满足实际的应用需求,就已经差不多了。
从设计的角度来看,busybox的源码和linux内核、u-boot源码一样,具有出色的设计思维和优秀的构建思想在里面,小生的文章仅仅是冰山一角啦!
???? 站在巨人的肩膀上,『敬畏』、『热情』、『分享』
应该还有一篇,是关于login
程序和ash
程序的......