Busybox

来自资料库(何亚红)
跳转到导航 跳转到搜索

源代码

主要

https://git.busybox.net/busybox

备用

https://github.com/mirror/busybox.git

说明

busybox可提供许多UNIX工具(多数是简化版,提供基础的功能),而只需要一个单文件(可使用软连接指向busybox以创建busybox支持的命令)。

busybox常用于存储比较受限的系统,如在Flash的嵌入式系统。

优点是体积小缺点是只支持基本功能。

常用编译命令参数如下:

项目 类型 说明 备注
menuconfig Makefile目标 使用菜单配置内核 第一次编译需要先初始化Kconfig配置,可使用此目标(也可使用其它目标,具体使用make help查看)
install Makefile目标 安装busybox 安装的目标目录由KconfigCONFIG_PREFIX决定,默认是./_install
CROSS_COMPILE 环境变量/Makefile变量 指定交叉编译工具链前缀 如若要使用arm-linux-guneabihf-gcc则可指定CROSS_COMPILE=arm-linux-guneabihf-
LDFLAGS 环境变量/Makefile变量 链接参数 一般使用LDFLAGS="-static -static-libstdc++ -static-libgcc" 静态链接busybox

相关Linux发行版/工具

  • tinycorelinux:一个体积极小的Linux系统项目。作用类似Windows的PE,主要运行一些维护工具或者黑客工具(如WIFI破解)。注意:工具需要自行集成或者下载修改好的镜像。
  • slitaz:安全、高性能的Linux操作系统。
  • alpine:一个基于musl libc与busybox的安全导向的轻量Linux发行版。主要用于docker镜像。
  • openwrt:操作系统。一般用于路由器方案,为减小rootfs体积大小默认采用musl libc+busybox,也可使用glibc+busybox。
  • buildroot:嵌入式Linux构建工具。可创建基于busybox的rootfs,也可创建使用systemd作为init的系统。

以上发行版/工具可用于测试busybox或者参考他们的文件系统。

基本文件系统

目录

一般情况下,若要挂载各种文件系统则需要目录存在,故需要预先创建一个基本的目录结构。

以下目录为约定俗成的Linux最小根文件系统目录(保证正常启动及应用执行,不包含编译环境等):

目录 说明
/bin 二进制可执行文件目录,系统级(一般是启动相关)二进制文件。注意:包括可执行的脚本文件。
/boot 启动文件目录,包含内核、设备树、Bootloader相关配置文件。
/dev 设备文件目录,此目录一般挂载为tmpfs,在busybox为主的根文件系统中一般由mdev管理。
/etc 配置文件目录,一般情况下应用程序的配置文件均存放在此目录。
/home 非root用户家目录。若无其他用户则不需要。
/lib 库文件目录。
/lib/modules/ 对于Linux而言,为内核模块目录。
/lib/firmware/ 对于Linux而言,为固件目录。
/opt 可选目录,其目录结构可类似/usr。

可创建可选软件目录,可选软件一般会在/opt建立一个目录,把所有文件按照类似/usr放入此目录,然后放一些启动脚本、桌面入口等放入(或者软链接)/usr对应的目录中。 可选软件的优点:

  • 便于更新或删除,直接操作/opt目录下的文件即可。
  • 应用可以将自己的所有依赖放入自己的目录,不依赖系统中的部分其他软件。安装过程中可使用patchelf修改ELF interpreter路径及ELF可执行文件的库目录。

可选软件的缺点:

  • 由于没有遵循系统目录结构,大量的搜索目录环境变量或者应用自身需要的环境变量需要修改,一般由启动脚本解决。
  • 系统中应用一般情况下在未特殊设置时不能访问可选软件的共享文件,会导致可选软件不能完美嵌入系统,一般由软链接解决,但软链接太多又失去了可选软件的意义。

在嵌入式应用中一般把GUI相关软件应用与库放在/opt目录,修改应用时直接修改/opt下的目录。

/proc proc文件系统挂载目录。十分关键,若不挂载可能导致部分应用不可执行。
/root root用户家目录。
/run 运行目录。主要存放如pid文件、unix文件socket文件、管道文件等,一般用于ipc。可挂载为tmpfs。对于早期版本目录结构而言,此目录路径可能为/var/run,为做兼容,可将/var/run 软链接到/run
/sbin 特权(需要root执行)二进制可执行文件目录,系统级(一般是启动相关)二进制文件。注意:包括可执行的脚本文件。
/sys sysfs文件系统挂载目录。十分关键,若不挂载可能导致部分应用不可执行。
/tmp 临时文件目录。一般挂载为tmpfs,在根文件系统可读写情况下也可不挂载tmpfs.
/usr unix软件资源。非系统级文件级(启动无关,通常是应用)文件目录,包括但不限于二进制可执行文件、二进制库文件、应用共享文件、头文件、源代码文件等。
/usr/bin 类似/bin
/usr/sbin 类似/sbin
/usr/lib 类似/lib,但只包含库文件,不包含Linux内核模块与固件文件。
/usr/local 本地文件目录,目录结构类似/usr(不包含local目录),一般用于存放本地编译的程序(配置文件、二进制文件等)。
/usr/share 共享文件目录,存放应用可共享给其他应用的文件(如man手册等)。对GUI应用而言,此目录包含各种GUI资源。
/var 可变文件目录。主要存放日志、缓存、可变资源文件(如网站数据、数据库数据)等。

init程序

截止编辑时Linux内核的init程序查找执行顺序(当查找到任意一个就直接执行并作为init程序):

  1. ramdisk初始化程序:/init。
  2. 内核命令中的init选项,即init=后的参数。
  3. Kconfig中的CONFIG_DEFAULT_INIT选项。
  4. 其他可执行文件,依次为/sbin/init、/etc/init、/bin/init、/bin/sh。

当未查找到init程序时,Linux内核将报错。

init作为根文件系统中第一个启动的用户程序便是整个根文件系统的入口,可以是二进制可执行文件,也可是脚本,但需要注意的是,init程序不可退出,如真的需要退出可使用exec命令(或exec函数)直接将控制权移给另一个程序。

在busybox为主的根文件系统中一般使用软链接将/init与/sbin/init指向/bin/busybox,即使用busybox的init命令。

busybox的init命令

默认情况下,init命令会运行系统初始化脚本(/etc/init.d/rcS)并在init所在控制台提示可打开一个shell。

/etc/init.d/rcS由用户编写,应当完成的任务如下:

  • 挂载各种文件系统(如proc文件系统、sysfs文件系统等)
  • 初始化目录(如创建各种目录,使用mdev管理/dev目录等)
  • 启动守护进程(由用户设计,一般情况下时遍历并启动/etc/init.d下 的其他脚本)

当启用了inittab并存在/etc/inittab时,init命令按照inittab规定的行为(包括系统初始化行为、按住ctrl+alt+del时的行为、关机行为、重启行为、tty终端行为)执行。

busybox的inittab说明如下:

# /etc/inittab init(8) configuration for BusyBox
#
# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
#
#
# Note, BusyBox init doesn't support runlevels.  The runlevels field is
# completely ignored by BusyBox init. If you want runlevels, use sysvinit.
#
#
# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# <id>: WARNING: This field has a non-traditional meaning for BusyBox init!
#
#	The id field is used by BusyBox init to specify the controlling tty for
#	the specified process to run on.  The contents of this field are
#	appended to "/dev/" and used as-is.  There is no need for this field to
#	be unique, although if it isn't you may have strange results.  If this
#	field is left blank, then the init's stdin/out will be used.
#
# <runlevels>: The runlevels field is completely ignored.
#
# <action>: Valid actions include: sysinit, wait, once, respawn, askfirst,
#                                  shutdown, restart and ctrlaltdel.
#
#	sysinit actions are started first, and init waits for them to complete.
#	wait actions are started next, and init waits for them to complete.
#	once actions are started next (and not waited for).
#
#	askfirst and respawn are started next.
#	For askfirst, before running the specified process, init displays
#	the line "Please press Enter to activate this console"
#	and then waits for the user to press enter before starting it.
#
#	shutdown actions are run on halt/reboot/poweroff, or on SIGQUIT.
#	Then the machine is halted/rebooted/powered off, or for SIGQUIT,
#	restart action is exec'ed (init process is replaced by that process).
#	If no restart action specified, SIGQUIT has no effect.
#
#	ctrlaltdel actions are run when SIGINT is received
#	(this might be initiated by Ctrl-Alt-Del key combination).
#	After they complete, normal processing of askfirst / respawn resumes.
#
#	Note: unrecognized actions (like initdefault) will cause init to emit
#	an error message, and then go along with its business.
#
# <process>: Specifies the process to be executed and it's command line.
#
# Note: BusyBox init works just fine without an inittab. If no inittab is
# found, it has the following default behavior:
#	::sysinit:/etc/init.d/rcS
#	::askfirst:/bin/sh
#	::ctrlaltdel:/sbin/reboot
#	::shutdown:/sbin/swapoff -a
#	::shutdown:/bin/umount -a -r
#	::restart:/sbin/init
#	tty2::askfirst:/bin/sh
#	tty3::askfirst:/bin/sh
#	tty4::askfirst:/bin/sh
#
# Boot-time system configuration/initialization script.
# This is run first except when booting in single-user mode.
#
::sysinit:/etc/init.d/rcS

# /bin/sh invocations on selected ttys
#
# Note below that we prefix the shell commands with a "-" to indicate to the
# shell that it is supposed to be a login shell.  Normally this is handled by
# login, but since we are bypassing login in this case, BusyBox lets you do
# this yourself...
#
# Start an "askfirst" shell on the console (whatever that may be)
::askfirst:-/bin/sh
# Start an "askfirst" shell on /dev/tty2-4
tty2::askfirst:-/bin/sh
tty3::askfirst:-/bin/sh
tty4::askfirst:-/bin/sh

# /sbin/getty invocations for selected ttys
tty4::respawn:/sbin/getty 38400 tty5
tty5::respawn:/sbin/getty 38400 tty6

# Example of how to put a getty on a serial line (for a terminal)
#::respawn:/sbin/getty -L ttyS0 9600 vt100
#::respawn:/sbin/getty -L ttyS1 9600 vt100
#
# Example how to put a getty on a modem line.
#::respawn:/sbin/getty 57600 ttyS2

# Stuff to do when restarting the init process
::restart:/sbin/init

# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

设备文件

虽然/dev在在busybox为主的根文件系统中采用mdev管理,但在init启动时/dev尚未初始化,为保证init程序尤其是脚本正确运行,需要在/dev中预先放置一些设备文件。

让/dev在init程序启动时有部分设备文件的方法:

  • 在内核中启用devtmpfs并启用devtmpfs自动挂载。推荐使用此方法。
  • 在早期版本Linux根文件系统中,通常方法是在打包时就使用mknod命令在dev目录创建设备文件。这样打包根文件系统时预置了init程序或者shell程序需要的设备文件。

笔记

/dev/创建与更新

除了系统调用、proc文件系统、sysfs文件系统之外,在Linux应用打交道最多的便是/dev/,对于使用busybox作为init的系统而言,通常使用mdev作为创建/dev/与维护/dev的工具。

在启动时需要使用mdev -s 创建/dev,使用echo /sbin/mdev >/proc/sys/kernel/hotplug 设置在设备热插拔时更新/dev。

注意:在最新版Linux内核中可启用devtmpfs自动挂载一个/dev。

官方资料

网址:https://www.busybox.net

二进制文件下载:https://busybox.net/downloads/binaries/

相关资料