 | Level: Introductory M. Tim Jones (mtj@mtjones.com), Consultant Engineer, Emulex
15 Aug 2006 BusyBox is a single executable implementation of many standard Linux® utilities. BusyBox contains simple utilities, such as cat and echo, as well as larger, more complex tools, such as grep, find, mount, and telnet (albeit, with fewer options than the traditional version); some refer to BusyBox as the Swiss Army knife of utilities. This article explores the purpose of BusyBox, how it works, and why it's important for memory-constrained environments.
The birth of BusyBox
BusyBox was first written by Bruce Perens in 1996 for the Debian GNU/Linux
setup disk. The goal was to create a bootable GNU/Linux system on a single
floppy disk that could be used as an install and rescue disk. A single floppy
disk can hold around 1.4-1.7MB, so there's not much room available for the Linux kernel and associated user applications.
 |
BusyBox license
BusyBox is licensed under the GNU General Public License (GPL). This means
that if you use BusyBox in a project, you must abide by the license. You can
view the license on the BusyBox Web site (see the Resources section later in this article). The BusyBox team appears
to keep busy by monitoring violators of their license. In fact, they maintain a "Hall of
Shame" page to document violations.
|
|
BusyBox exploits the fact that the
standard Linux utilities share many common elements. For example, many file-based utilities (such as
grep and find) require
code to recurse a directory in search of files. When the utilities are combined
into a single executable, they can share these common elements, which results
in a smaller executable. In fact, BusyBox can pack almost 3.5MB of utilities
into around 200KB. This provides greater functionality to
bootable floppy disks and embedded devices that use Linux. You can use BusyBox
with both the 2.4 and 2.6 Linux kernels.
How does BusyBox work?
To make one executable look like many executables, BusyBox exploits a seldom-used feature of argument passing to the main C function. Recall that the C main function is defined as follows:
 |
POSIX environment
While BusyBox aims to provide a relatively complete Portable Operating System Interface (POSIX) environment, that's a desire and not a requirement. The utilities aren't complete, but they do provide the major functionality expected of them.
|
|
Listing 1. The C main function
int main( int argc, char *argv[] )
|
In this definition, argc is the number of arguments passed in
(argument count) and argv is an array of strings
representing options passed in from the command line (argument vector).
Index 0 of argv is the program name that was
invoked from the command line.
The simple C program shown in Listing 2 demonstrates BusyBox
invocation. It simply emits the contents of the argv
vector.
Listing 2. BusyBox uses argv[0] to determine which application to invoke
// test.c
#include <stdio.h>
int main( int argc, char *argv[] )
{
int i;
for (i = 0 ; i < argc ; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}
|
Invoking this application shows that the first argument invoked is the
name of the program. You can rename your executable, and you get
the new name upon invocation. Further, you can create a symbolic link to your
executable, and you get the symlink name when it's invoked.
Listing 3. Command testing after updating BusyBox with a new command
$ gcc -Wall -o test test.c
$ ./test arg1 arg2
argv[0] = ./test
argv[1] = arg1
argv[2] = arg2
$ mv test newtest
$ ./newtest arg1
argv[0] = ./newtest
argv[1] = arg1
$ ln -s newtest linktest
$ ./linktest arg
argv[0] = ./linktest
argv[1] = arg
|
BusyBox uses symbolic links to make one executable look like many. For each
of the utilities contained within BusyBox, a symbolic link is created so that
BusyBox is invoked. BusyBox then invokes the internal utility as defined
by argv[0].
Configuring and building BusyBox
You can download the latest version of BusyBox from its Web site (see the Resources section).
Like most open source programs, it's distributed in a compressed tarball, and you can transform it into a source tree using the command in Listing 4. (If you downloaded a version other than 1.1.1, use the appropriate version number in this and other version-specific commands.)
Listing 4. Untarring BusyBox
$ tar xvfz busybox-1.1.1.tar.gz
$
|
The result is a directory, called busybox-1.1.1, that contains the BusyBox source code. To build the default configuration, which
includes almost everything with debugging disabled, use the
defconfig make target:
 |
BusyBox source tree
The source tree for BusyBox is well organized. Utilities are
categorized based on their use and stored in separate subdirectories.
For example, the networking utilities and daemons (such as
httpd, ifconfig, and so on) are in the ./networking directory;
standard module utilities (including insmod,
rmmod and lsmod) are in
the ./modutils directory; and editors (such as vi, and
stream editors such as awk and
sed) are in the ./editors directory.
The makefiles and various documents
for configuring, building, and installing are at the root of the tree.
|
|
Listing 5. Building the default BusyBox configuration
$ cd busybox-1.1.1
$ make defconfig
$ make
$
|
The result is a rather large BusyBox image, but it's the simplest way to get
started. You can invoke this new image directly, which results in a simple
Help page with the currently configured commands. To test your image, you can also invoke BusyBox with a command to execute, as shown in Listing 6.
Listing 6. Demonstrating BusyBox command execution and the ash shell in BusyBox
$ ./busybox pwd
/usr/local/src/busybox-1.1.1
$ ./busybox ash
/usr/local/src/busybox-1.1.1 $ pwd
/usr/local/src/busybox-1.1.1
/usr/local/src/busybox-1.1.1 $ exit
$
|
In this example, you invoke the pwd (print working directory) command, enter the ash shell within BusyBox, and invoke pwd within ash.
Manual configuration
If you're building an embedded device that has very specific needs, you can
manually configure the contents of your BusyBox with the
menuconfig make target. If you're familiar with
building a Linux kernel, note that menuconfig is the same target for
configuring the contents of the Linux kernel. In fact, the ncurses-based
application is the same.
Using manual configuration, you can specify the commands to be included in the
final BusyBox image. You can also configure the BusyBox environment, such as
including support for the United States National Security Agency's (NSA) Security-Enhanced Linux (SELinux), specifying the
compiler to use (for cross-compiling in an embedded environment), and whether
BusyBox should be compiled statically or dynamically. Figure 1 shows the main
screen for menuconfig. Here you can see the different major classes of
applications (applets) that you can configure for BusyBox.
Figure 1. BusyBox configuration using menuconfig
 |
Multiple architecture support
Being able to easily specify the cross-compiler for BusyBox means that you
can build BusyBox for a wide variety of architectures. To build BusyBox
for your target architecture, you need a cross-compiler and a version of
the C library (uClibc or glibc) that has been compiled for the particular
target architecture.
|
|
To manually configure BusyBox, use the following commands:
Listing 7. Manually configuring BusyBox
$ make menuconfig
$ make
$
|
This provides you with a BusyBox binary that can be invoked. The next step is
to build an environment around BusyBox, including the symbolic links that
redirect the standard Linux commands to the BusyBox binary. You can do this
very simply with the following command:
Listing 8. Building the BusyBox environment
By default, a new local subdirectory is created, called _install, which contains the basic Linux environment.
At the root, you'll find a linuxrc program that links to
BusyBox. The linuxrc program is useful when building an
install or rescue disk (permits a modularized boot prior). Also at the root is a /sbin subdirectory that contains operating system binaries (used primarily for administration), and a /bin subdirectory that contains binaries intended for users.
You can then migrate this _install directory into your target environment when building a floppy
distribution or embedded initial RAM disk. You can also use the
PREFIX option with the make program to redirect the install
subdirectory to a new location. For example, the following code segment
installs the symlinks using the /tmp/newtarget root directory instead of the ./_install directory:
Listing 9. Installing symlinks to another directory
$ make PREFIX=/tmp/newtarget install
$
|
The links that are created through the
install make target come from the
busybox.links file. This file is created when
BusyBox is compiled, and it contains the list of commands that have been
configured. When install is performed, the
busybox.links file is checked for the symlinks to
create.
The command links to BusyBox can also be created dynamically at runtime
using BusyBox. The CONFIG_FEATURE_INSTALLER option
enables this feature, which can be performed at runtime as follows:
Listing 10. Creating command links at runtime
$ ./busybox --install -s
$
|
The -s option forces symbolic links to be
created (otherwise, hard links are created). This option requires that the
/proc file system is present.
BusyBox build options
BusyBox includes several build options to help you build and debug the
right BusyBox for you.
Table 1. Some of the make options available for BusyBox
| make target | Description |
|---|
help
| Show the complete list of make options |
defconfig
| Enable a default (generic) configuration |
allnoconfig
| Disable all applications (empty configuration) |
allyesconfig
| Enable all applications (complete configuration) |
allbareconfig
| Enable all applications, but no subfeatures |
config
| Text-based configurator |
menuconfig
| N-curses (menu-based) configurator |
all
| Build the BusyBox binary and documentation (./docs) |
busybox
| Build the BusyBox binary |
clean
| Clean the source tree |
distclean
| Completely clean the source tree |
sizes
| Emit the text/data sizes of the enabled applications |
When a configuration is defined, you just need to type make to actually
build the BusyBox binary. For example, to build BusyBox for all applications,
you can do the following:
Listing 11. Building the BusyBox binary
$ make allyesconfig
$ make
$
|
Shrinking BusyBox
If you're really serious about shrinking the size of your BusyBox image, here
are two things to keep in mind:
- Never build as a static binary (which includes all needed libraries in the image). Instead, if you build as
a shared image, it uses the available libraries that are used by other
applications (for example,
/lib/libc.so.X).
- Build with the uClibc, which is a size-optimized C library that was developed for
embedded systems, rather than building with the standard glibc (GNU C library).
Options supported in BusyBox commands
The commands in BusyBox don't support all of the options commonly available,
but they do contain the options that are used most often. If you need to know which options
are supported for a command, you can invoke and use the --help
option, as shown in Listing 12.
Listing 12. Invoking the --help option
$ ./busybox wc --help
BusyBox v1.1.1 (2006.04.09-15:27+0000) multi-call binary
Usage: wc [OPTION]... [FILE]...
Print line, word, and byte counts for each FILE, and a total line if
more than one FILE is specified. With no FILE, read standard input.
Options:
-c print the byte counts
-l print the newline counts
-L print the length of the longest line
-w print the word counts
$
|
This particular data is available only if the CONFIG_FEATURE_VERBOSE_USAGE
option is enabled. Without this option, you won't get the verbose data,
but you'll also save about 13KB.
Adding new commands to BusyBox
Adding a new command to BusyBox is simple because of its well-defined architecture. The first step is to choose a location for your new command's source. Select the location based on the type of command
(networking, shell, and so on), and be consistent with other commands. This is important because your new command will ultimately show up in the
particular configuration menu for menuconfig (in this case, in the Miscellaneous Utilities menu).
For this example, I've called the new command
(newcmd) and placed it in the ./miscutils directory. The new command's source is shown in Listing 13.
Listing 13. Source for new command to integrate into BusyBox
#include "busybox.h"
int newcmd_main( int argc, char *argv[] )
{
int i;
printf("newcmd called:\n");
for (i = 0 ; i < argc ; i++) {
printf("arg[%d] = %s\n", i, argv[i]);
}
return 0;
}
|
Next, add your new command source to
Makefile.in in the chosen subdirectory. In this
example, I update ./miscutils/Makefile.in.
Add your new command in alphabetical order to maintain consistency with the
existing commands:
Listing 14. Adding command to Makefile.in
MISCUTILS-$(CONFIG_MT) += mt.o
MISCUTILS-$(CONFIG_NEWCMD) += newcmd.o
MISCUTILS-$(CONFIG_RUNLEVEL) += runlevel.o
|
Next, update the configuration file, again within
the ./miscutils directory, to make your new command visible within the configuration process. This file is called
Config.in, and your new command is added in
alphabetical order:
Listing 15. Adding command to Config.in
config CONFIG_NEWCMD
bool "newcmd"
default n
help
newcmd is a new test command.
|
This structure defines a new config entry (through the
config keyword) and then the config option
(CONFIG_NEWCMD). Your new command will either be
enabled or disabled, so use the bool (Boolean)
menu attribute for configuration. Its default is disabled
(n for No), and you end with a short Help description. You can see the entire grammar for the configuration syntax in the source tree at
./scripts/config/Kconfig-language.txt.
Next, update the ./include/applets.h file to include your new command. Add the following line to this file,
remembering to keep it in alphabetical order. It's important to maintain this
order, otherwise your command will not be found.
Listing 16. Adding command to applets.h
USE_NEWCMD(APPLET(newcmd, newcmd_main, _BB_DIR_USER_BIN, _BB_SUID_NEVER))
|
This defines your command name (newcmd), its
function name in the Busybox source (newcmd_main),
where the link will be created for this new command (in this case, in the /usr/bin directory), and, finally, whether the command has permissions to set the user id (in this case, no).
The penultimate step is to add detailed Help information to the ./include/usage.h file. As you'll see from examples in this file, usage information can be quite verbose. In this case, I've just added a little information so I can build the new command:
Listing 17. Adding help information to usage.h
#define newcmd_trivial_usage "None"
#define newcmd_full_usage "None"
|
The final step is to enable your new command (through make menuconfig and then enable the option in the Miscellaneous Utilities menu) and then build BusyBox with make.
With your new BusyBox available, you can test your new command, as shown in Listing 18.
Listing 18. Testing your new command
$ ./busybox newcmd arg1
newcmd called:
arg[0] = newcmd
arg[1] = arg1
$ ./busybox newcmd --help
BusyBox v1.1.1 (2006.04.12-13:47+0000) multi-call binary
Usage: newcmd None
None
|
That's it! The BusyBox developers made a tool that's not only great but also simple to extend.
Summary
BusyBox is a great tool for building memory-constrained embedded systems
and also floppy-disk based systems. BusyBox shrinks the size of a variety of
necessary tools and utilities by pulling them together into a single
executable and allowing them to share the common aspects of their code. BusyBox is a useful
tool for your embedded toolbox and, therefore, worth your time to explore.
Resources Learn
-
uClibc is a reduced memory footprint
replacement for glibc.
While requiring fewer resources than glibc, porting applications to
uClibc typically requires only a recompile.
- The POSIX FAQ at the
Open Group can help you learn more about POSIX. Part three of this specification details shells and
utilities in particular.
-
LinuxTiny is a series of patches that reduce the memory and disk footprint of the 2.6 Linux kernel to as little as 2MB of RAM. If you're interested in shrinking
the 2.6 Linux kernel, check out this work by Matt Mackall.
-
In the developerWorks Linux zone, find more resources for Linux developers.
-
Stay current with developerWorks technical events and Webcasts.
Get products and technologies
- Download the latest release
of BusyBox. You'll also find the latest news, erratum, and tutorials for
using and amending BusyBox.
-
Order the SEK for Linux, a two-DVD set containing the latest IBM trial software for Linux from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
-
With IBM trial software, available for download directly from developerWorks, build your next development project on Linux.
Discuss
About the author  | 
|  | M. Tim Jones is an embedded software architect and the author of GNU/Linux Application Programming, AI Application Programming, and BSD Sockets Programming from a Multilanguage Perspective. His engineering background ranges from the development of kernels for geosynchronous spacecraft to embedded systems architecture and networking protocols development. Tim is a Consultant Engineer for Emulex Corp. in Longmont, Colorado. |
Rate this page
|  |