Book Image

Instant Optimizing Embedded Systems Using BusyBox

Book Image

Instant Optimizing Embedded Systems Using BusyBox

Overview of this book

As hundreds of millions of people have started using Android smartphones, embedded Linux systems are becoming more and more popular. To get more market share, not only for hardware and function piling up, smartphone manufacturers gradually realized the importance of user experience. To improve user experience, the back-end Linux system must be optimized in many ways. Instant Optimizing Embedded System Using BusyBox is a practical, hands-on guide that provides you with a number of clear, step-by-step exercises to help you take advantage of the real power behind Busybox, and give you a good grounding for using it to optimize your embedded (Android Linux) systems. Moving on from the basics, this book will teach you how to configure and compile it from source code, including cross-compiling it with static linking and dynamic linking. You will also learn how to install and use Busybox on the Android emulator. You will learn to replace the simple Android mksh console with Busybox ash console and start a telnet and HTTP service provided by Busybox. You will also build embedded Linux file system from scratch and start it on Android emulator. We will take a look at how to add functionality to Busybox based system, including adding external applets to Busybox, as well as building development environments (like Bash and C) for it manually or with the automatic Buildroot system. If want to learn how to take advantage of using Busybox applets to optimize your embedded system, then this is the book for you for it will also show you how to use the powerful applets to optimize multiple aspects of an embedded (Android Linux) system.This book will teach you how to build an embedded (Android Linux) system with Busybox, enhance its functionality to meet diverse system requirements, and optimize it to provide a better user experience for embedded products.
Table of Contents (8 chapters)

Compiling BusyBox (Simple)


After configuration, BusyBox can be compiled into a single binary for different architectures, with different compilers and with static or dynamic linking.

This recipe will compile BusyBox for our desktop development system as a quick demonstration, and meanwhile, build BusyBox for an ARM target platform as an embedded system case.

Getting ready

Before compiling a software, we must get a compiler and the corresponding libraries, a build host, and a target platform. The build host is the one running the compiler. The target platform is the one running the target binary built by the compiler from the software source code. Here, our desktop development system is our build host, and an ARM Android system will be used as our target platform.

To compile BusyBox on our desktop development system, we need a local compiler. Generally, most Linux operating systems ship with a working C compiler, and it's usually GCC (the GNU Compiler Collection is by far the most widely used C compiler on Linux, and can be downloaded from http://gcc.gnu.org/) and the corresponding Glibc (the GNU C Library by far is the most widely used C library on Linux and can be downloaded from http://www.gnu.org/software/libc/). If it isn't present, get one from our system's package manager for Ubuntu.

$ sudo apt-get install gcc g++ make build-essential
$ sudo apt-get install ia32-libs ia32-libs-multiarch

To compile BusyBox on our desktop development system for a different target architecture (for example, an ARM Android system), we need a cross-compiler.

ARM, as the most popular architecture on embedded system, is being used by more and more portable devices, such as the embedded Raspberry Pi board and the Android mobile phone or tablet, so we will concern ourselves with this alone.

The gcc-arm-linux-gnueabi cross-compiler can be installed directly on Ubuntu with the following command:

$ sudo apt-get install gcc-arm-linux-gnueabi

On other Linux distributions, Google's official NDK is a good choice if you want to share Android's Bionic C library, but since Bionic C library lacks of many POSIX C header files, and because we want to get the most out of BusyBox applets building, the prebuilt version of Linaro GCC with Glibc is preferable. We can download it from http://www.linaro.org/downloads/; for example, http://releases.linaro.org/13.04/components/toolchain/binaries/gcc-linaro-aarch64-none-elf-4.7-2013.04-20130415_linux.tar.bz2.

How to do it...

Let's compile BusyBox with the default configuration for our desktop development system as a quick demonstration of the compiling procedure and cross-compile it for the ARM platform as a real embedded system building example.

  1. Compiling BusyBox for a desktop development system can be done as follows:

    $ make defconfig
    $ make
    $ file busybox
    busybox: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs)...
    $ ldd busybox
       linux-vdso.so.1 =>  (0x00007fff9edff000)
       libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1cf2cb4000)
       libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1cf28f5000)
       /lib64/ld-linux-x86-64.so.2 (0x00007f1cf2fcf000)
    

    The previous lines of code compiled a binary for our x86-64 development system (the output may differ if you are using a different development system) and dynamically linked it with libm.so and libc.so.

  2. To get a quick start, simply run the echo applet as an example.

    $ ./busybox echo "Hello, Busybox."
    Hello, Busybox.
    
  3. To get help from BusyBox and its applets, we can append the --help command as follows:

    $ ./busybox --help
    

    We see the following output:

    BusyBox v1.21.0 (2013-09-06 01:24:09 CST) multicall binary.
    BusyBox is copyrighted by many authors between 1998-2012. Licensed under GPLv2. See source distribution for detailed copyright notices.
    Usage: busybox [function [arguments]...]
       or: busybox --list[-full]
       or: busybox --install [-s] [DIR]
       or: function [arguments]...
    BusyBox is a multicall binary that combines many common Unix utilities into a single executable file. Most people will create a link to busybox for each function they wish to use and BusyBox will act like whatever it was invoked as. Currently defined functions:
    [, [[, acpid, add-shell, addgroup, adduser, adjtimex, arp, arping, ash, awk, base64, basename, beep, blkid, blockdev, bootchartd, brctl, bunzip2, bzcat, bzip2, cal, cat, catv, chat, chattr, 
    chgrp, chmod, chown, chpasswd, chpst, chroot, chrt, chvt, cksum, clear, cmp, comm, conspy, cp, cpio, crond, crontab, cryptpw, cttyhack, cut, date, dc, dd, deallocvt, delgroup, deluser, depmod, devmem, df, dhcprelay, diff, dirname, dmesg, dnsd, dnsdomainname, dos2unix, du, dumpkmap, dumpleases, echo, ed, egrep, eject, env, envdir, envuidgid, ether-wake, expand, expr, fakeidentd, false, fbset, fbsplash, fdflush, fdformat, fdisk, fgconsole, fgrep, find, findfs, flock, fold, free, freeramdisk, fsck, fsck.minix, fsync, ftpd, ftpget, ftpput, fuser, getopt, getty, grep, groups, gunzip, gzip, halt, hd, hdparm, head, hexdump, hostid, hostname, httpd, hush, hwclock, id, ifconfig, ifdown, ifenslave, ifplugd, ifup, inetd, init, insmod, install, ionice, iostat, ip, ipaddr, ipcalc, ipcrm, ipcs, iplink, iproute, iprule, iptunnel, kbd_mode, kill, killall, killall5, klogd, last, less, linux32, linux64, linuxrc, ln, loadfont, loadkmap, logger, login, logname, logread, losetup, lpd, lpq, lpr, ls, lsattr, lsmod, lsof, lspci, lsusb, lzcat, lzma, lzop, lzopcat, makedevs, makemime, man, md5sum, mdev, mesg, microcom, mkdir, mkdosfs, mke2fs, mkfifo, mkfs.ext2, mkfs.minix, mkfs.vfat, mknod, mkpasswd, mkswap, mktemp, modinfo, modprobe, more, mount, mountpoint, mpstat, mt, mv, nameif, nanddump, nandwrite, nbd-client, nc, netstat, nice, nmeter, nohup, nslookup, ntpd, od, openvt, passwd, patch, pgrep, pidof, ping, ping6, pipe_progress, pivot_root, pkill, pmap, popmaildir, poweroff, powertop, printenv, printf, ps, pscan, pstree, pwd, pwdx, raidautorun, rdate, rdev, readahead, readlink, readprofile, realpath, reboot, reformime, remove-shell, renice, reset, resize, rev, rm, rmdir, rmmod, route, rpm, rpm2cpio, rtcwake, run-parts, runlevel, runsv, runsvdir, rx, script, scriptreplay, sed, sendmail, seq, setarch, setconsole, setfont, setkeycodes, setlogcons, setserial, setsid, setuidgid, sh, sha1sum, sha256sum, sha3sum, sha512sum, showkey, slattach, sleep, smemcap, softlimit, sort, split, start-stop-daemon, stat, strings, stty, su, sulogin, sum, sv, svlogd, swapoff, swapon, switch_root, sync, sysctl, syslogd, tac, tail, tar, tcpsvd, tee, telnet, telnetd, test, tftp, tftpd, time, timeout, top, touch, tr, traceroute, traceroute6, true, tty, ttysize, tunctl, ubiattach, ubidetach, ubimkvol, ubirmvol, ubirsvol, ubiupdatevol, udhcpc, udhcpd, udpsvd, umount, uname, unexpand, uniq, unix2dos, unlzma, unlzop, unxz, unzip, uptime, users, usleep, uudecode, uuencode, vconfig, vi, vlock, volname, wall, watch, watchdog, wc, wget, which, who, whoami, whois, xargs, xz,xzcat, yes, zcat, zcip.
    

    Also we can use the echo command as follows:

    $ ./busybox echo --help
    BusyBox v1.21.0 (2013-10-16 01:24:09 CST) multi-call binary.
    Usage: echo [-neE] [ARG]...
    Print the specified ARGs to stdout
    
       -n	Suppress trailing newline
       -e	Interpret backslash escapes (i.e., \t=tab)
       -E	Don't interpret backslash escapes (default)
    
  4. Now cross-compile it for the ARM platform. To compile it for the ARM platform, the cross-compiler arm-linux-gnueabi-gcc should be configured with make menuconfig, as we demonstrated in the previous recipe. After configuration, we can simply compile it as follows:

    $ make
    
  5. Then a BusyBox binary is compiled for ARM with dynamic linking as follows:

    $ file busybox
    busybox: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
    
  6. The previous ldd command of our development system doesn't work for listing the shared libraries required by the BusyBox binary for ARM,. Another command should be used instead, arm-linux-gnueabi-readelf, as follows:

    $ arm-linux-gnueabi-readelf -d ./busybox | grep "Shared library:" \
       | cut -d'[' -f2 | tr -d ']'
    libm.so.6
    libc.so.6
    ld-linux.so.3
    
  7. To get the full path, we should first use the library search path.

    $ arm-linux-gnueabi-ld --verbose | grep SEARCH \
       | tr ';' '\n' | cut -d'"' -f2 | tr -d '"'
    /lib/arm-linux-gnueabi
    /usr/lib/arm-linux-gnueabi
    /usr/arm-linux-gnueabi/lib
    
  8. Then we find out that /usr/arm-linux-gnueabi/lib is the real search path in our platform and we get the full path of the libraries as follows:

    $ ls /usr/arm-linux-gnueabi/lib/{libm.so,libc.so,ld-linux.so.3}
    /usr/arm-linux-gnueabi/lib/ld-linux.so.3  /usr/arm-linux-gnueabi/lib/libc.so  /usr/arm-linux-gnueabi/lib/libm.so
    

Using BusyBox on an ARM platform needs an ARM device. This will be introduced in the Creating a virtual Android device (Simple) and Playing BusyBox on a virtual Android device (Intermediate) recipes.

How it works...

The configuration not only generates a .config file with enabled features, but also produces a C header file, include/autoconf.h, that enables or disables the features with C macros. Based on these macros, the compiler determines which C context should be built in the last binary.

There's more...

By default, the binary is dynamically linked. To avoid the installation of shared libraries, to reduce the whole system size, and to reduce the time cost of runtime linking, static linking is often used for embedded system compiling.

To enable static linking, configure BusyBox as follows:

   Busybox Settings --->
      Build Options --->
          [*] Build BusyBox as a static binary (no shared libs)

We get the following error when using a new Glibc to compile BusyBox with static linking:

inetd.c:(.text.prepare_socket_fd+0x7e): undefined reference to `bindresvport'

We need to disable CONFIG_FEATURE_INETD_RPC, as follows, to avoid it:

   Networking Utilities  --->
       [*] inetd
           [ ]   Support RPC services

Then, recompile it as follows:

$ make

Because it is statically linked, the required libraries will be linked into the last BusyBox binary. To run it on the target system, you only need to install the BusyBox binary (no shared libraries need to be installed).

The installation of BusyBox will be discussed in next recipe and the Creating a virtual Android device (Simple) recipe.