BusyBox can be used as a toolbox on existing systems, and it is also often used to build a bootable embedded system.
Let's build a standalone system with BusyBox from scratch and launch it on a virtual Android device with an Android emulator.
This recipe will use BusyBox to build our own filesystem and compress it to a
gzipped cpio package, just like
ramdisk.img, which we used in the previous recipe.
To boot such a new system, a new Linux kernel image should be compiled from Google Android-specific Linux kernel source code. Clone the source code for preparation.
$ cd ~/tools/busybox/ $ git clone https://android.googlesource.com/kernel/goldfish.git
The source code is specifically designed for Android goldfish hardware; the Android emulator won't run on other hardware.
To cross-compile an Android Linux kernel, the cross-compiler
arm-linux-gnueabi-gcc should have been installed when going through the Compiling BusyBox recipe.
Based on the Installing BusyBox recipe, let's build our own filesystem:
ramdisk.img with BusyBox from scratch, cross-compile our own Linux kernel image, and then boot them on the Android emulator:
Build a minimal Linux filesystem with BusyBox. To build a minimal bootable filesystem, the standard Linux filesystem directory architecture should be prepared at first.
Apart from the
/usrdirectories that are created by default, the
/etcdirectories must be created manually:
$ cd ~/tools/busybox/ramdisk/ $ mkdir dev sys etc proc
/etccontains the configuration files for the Linux system. It includes two important files:
inittabcan be used by
initto determine which programs should be run and
fstabdescribes the filesystems mounting parameters. The
initprocess is the first process invoked by the Linux kernel after the kernel finishes its initialization (to learn more about the generic boot sequence of a Linux system, read the manual page of the boot process by running the
$ cat > ./etc/inittab ::sysinit:/etc/init.d/rcS ttyS2::askfirst:/bin/sh ::restart:/sbin/init $ cat > ./etc/fstab proc /proc proc defaults 0 0 sysfs /sys sysfs defaults 0 0 $ mkdir ./etc/init.d $ cat > ./etc/init.d/rcS #!/bin/sh mount -a echo /sbin/mdev > /proc/sys/kernel/hotplug mdev -s $ chmod 777 ./etc/init.d/rcS $ ln -s ./sbin/init init
With the previous setting, during the booting of our Linux system, the
initprocess parses our
inittabfile and runs
/etc/init.d/rcSas the first action. It mounts all filesystems specified in
fstab, and starts the minimal
mdevdevice management tool (like the more famous tool,
udev) to create all device nodes exported by low-level drivers under
/devfor late operations. It also creates a console with
/bin/sh, and attaches it at
/sbin/initis the first user process, the
/etc/inittabalso let it respawn for system availability.
Lastly, the console based on
/bin/shis provided as the basic shell environment for the user interaction.
Package the filesystem into an image and name it
Now, let's compress it with the following command:
$ cd ramdisk/ $ find . | cpio -H newc -o | gzip -9 > ../ramdisk.img
Cross-compile a new Android Linux kernel.
To start our own ramdisk, since it doesn't work with the prebuilt kernel image (zImage) in Android ADT (Android Development Toolkit), we should build our own Linux kernel image from the Android Linux kernel source code. Go to the just downloaded
goldfish/directory and compile it as follows:
$ cd ~/tools/busybox/goldfish/ $ git checkout android-goldfish-3.4 $ make goldfish_armv7_defconfig $ export CROSS_COMPILE=arm-linux-gnueabi- $ make zImage $ cp arch/arm/boot/zImage ~/tools/busybox/
Run our new embedded system on a virtual Android device.
Now, start our own kernel image with the just-built minimal filesystem as follows:
$ emulator @busybox-avd -shell -show-kernel -no-window \ -kernel ./zImage -ramdisk ./ramdisk.img Uncompressing Linux... done, booting the kernel. ... Please press Enter to activate this console.
According to this message, we can press Enter to activate the console terminal and execute the commands that we want to run.
ramdisk.img is an archive of format
gzipped cpio, which is extracted as the default root filesystem when the kernel boots up. It generally contains a file named
init, which will run after the kernel boots up. This
init command parses the initialization configuration,
/etc/inittab, and eventually starts the console based on the
ash shell, and provides the applets' running environment.
In real embedded development with the minimal filesystem built with BusyBox and their built-in applets, we are able to verify the function and robustness of their device drivers through their exported
With the help of the
ash applet, shell scripts can be written to perform test automation to enhance the stability of an embedded system. With the help of the built-in PowerTop, bootchartd, top, iostat, devmem, and some other external utilities, the other aspects of an embedded system can be optimized to provide better user experience. The test automation and system optimization will be discussed in the coming recipes.