BusyBox simplifies embedded Linux systems
来源:互联网 发布:js 判断是否是对象 编辑:程序博客网 时间:2024/06/06 20:16
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 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:
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]
.
Back to top
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:
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
.
Back to top
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
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
$ make install
$
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.
Back to top
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
help
Show the complete list of make optionsdefconfig
Enable a default (generic) configurationallnoconfig
Disable all applications (empty configuration)allyesconfig
Enable all applications (complete configuration)allbareconfig
Enable all applications, but no subfeaturesconfig
Text-based configuratormenuconfig
N-curses (menu-based) configuratorall
Build the BusyBox binary and documentation (./docs)busybox
Build the BusyBox binaryclean
Clean the source treedistclean
Completely clean the source treesizes
Emit the text/data sizes of the enabled applicationsWhen 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
$
Back to top
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).
Back to top
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:
-cprint the byte counts
-lprint the newline counts
-Lprint the length of the longest line
-wprint 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.
Back to top
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.
Back to top
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.
- With IBM trial software, available for download directly from developerWorks, build your next development project on Linux.
Discuss
- Check out developerWorksblogs and get involved in the developerWorks community.
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 forgeosynchronous spacecraft to embedded systems architecture andnetworking protocols development. Tim is a Consultant Engineer forEmulex Corp. in Longmont, Colorado.
- BusyBox simplifies embedded Linux systems
- Building Embedded Linux Systems
- 10010.Building Tiny Linux Systems with Busybox
- 读书笔记《Building embedded linux systems》Chapter 1
- 读书笔记《Building embedded linux systems》Chapter 2
- Embedded Linux: Using Compressed File Systems
- Embedded systems interview questions
- Embedded Systems Memory Types
- BusyBox - The Swiss Army Knife of Embedded Linux
- GNU Tools for Embedded Systems
- Design of Embedded Systems (DES)
- Real-Time Concepts for Embedded Systems----读书笔记
- Memory Leak Detection in Embedded Systems
- Real-Time Concepts for Embedded Systems
- Arm 学习笔记 第一章: Arm embedded systems
- Writing Efficient C Code for Embedded Systems
- Design Patterns for Embedded Systems in C
- Using ODB on Mobile and Embedded Systems
- 对象序列化 代码
- Jquery之Ajax
- 有关javascript中的this
- 一款新方块游戏
- 敏捷开发工具scrum
- BusyBox simplifies embedded Linux systems
- JAVA23种设计模式(另类思想)
- VC用ADO访问数据库全攻略
- hook 内核的体会
- resin 远程调试
- zoj 1239 Hanoi Tower Troubles Again!
- ado方式操作数据库类
- Android各种信息的显示
- tcp网络传输对象输入与输出流