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)

Tailoring the system size of an embedded (Android) system (Advanced)


We have now discussed the basic configuration, compiling, installation, and usage of BusyBox on virtual Android devices and demonstrated how to build a bootable embedded system with BusyBox from scratch and enhanced the system through integrating additional utilities, including lightweight applets, standalone tools, and even programming language environments. In short, the functionality implementation of a scalable embedded system with BusyBox has been discussed in depth in previous recipes.

This recipe onwards, we will learn how to enhance user experience—it's time to talk about system optimization. Size optimization will be discussed in this recipe.

Getting ready

For most embedded systems (particularly consumer electronics like smartphone systems), due to the limitation of product cost, size of the hardware model, and rich-function requirements, system image size should be limited to fit the size of the disk and memory and reserve more free storage for end users.

How to do it...

The software of an embedded Linux system mainly includes bootloader, kernel, ramdisk, system, and applications. Use the embedded filesystem we just built with BusyBox in the Building BusyBox-based embedded system (Intermediate) recipe as an example. To reduce its size, we should:

  1. Demand determine features:

    Remove the functions that are not required by the target system by disabling those features, via the configuration utility.

    For example, use defconfig as a configuration base and enable the necessary features and disable the rest.

  2. Share common features in libraries:

    When adding new features to BusyBox, try to use the library functionality already present in BusyBox and remove the code from the utility that duplicates that functionality.

    For example, for the sstrip program we just integrated, if some of its functions already exist in the common libraries of BusyBox, they should be removed.

  3. Static linking versus dynamic linking:

    If possible, link BusyBox with a lightweight standard library such as uClibc (http://www.uclibc.org/; it is optimized for an embedded system and is smaller than Glibc), not Glibc.

    If extra tools are required and support dynamic linking to share the same library, don't link BusyBox statically. But if you only need BusyBox, link statically to avoid the need of a dynamic linker and loader.

  4. Utilize compiler and linker support:

    Enable the -Os option of GCC by disabling the CONFIG_DEBUG_PESSIMIZE configuration option of BusyBox and enable --gc-sections using not Glibc (see the comments in scripts/trylink), and with a new enough ld tool.

  5. Strip everything that is not required at runtime:

    Use strip to discard symbols from object files, and use sstrip to remove the section header table at the end of the executable.

    It should be noted that an executable file that has no section header table cannot be used with gdb or objdump for debugging. You can learn more from the comments of sstrip.c.

  6. Compression is a technique with external perspective:

    Instead of optimizing the size of the filesystem, compressing the whole filesystem image with a suitable algorithm is a technique with external perspective. The algorithms include a general gzip or lzma format with higher compression rate, and LZO or LZ4 with lower compression rate but faster decompression speed.

    For example, the embedded filesystem we created in the Building BusyBox-based embedded system (Intermediate) recipe is packaged in cpio format and finally compressed with gzip.

    To use such algorithms, corresponding decompression support is required in bootloader, or else the Linux kernel for the filesystem will be unpacked into memory at boot time.

  7. Measure before starting optimization:

    Find the objects consuming large storage by measuring the size of each object or executable file and then optimize them one by one. The tools include ls -l, du, size, and nm –size.

    For example, the size utility can be used to output the size of different segments of an executable as follows:

    $ size busybox
       text   data    bss    dec    hex   filename
     824447   4154   9520  838121  cc9e9   busybox
    

How it works...

The main storage consumers of an embedded Linux system are executables. A standard Linux executable is in an ELF format. Besides an ELF header, a program header table, and a section header table, it consists of the text segment, data segment (initialized), and BSS segment (uninitialized).

To optimize size means to remove unnecessary executables or to reduce the size of the previously mentioned segments of the executables by sharing common functions or data, or even via sharing a single ELF header.

BusyBox is highly modular and configurable, and therefore allows to choose only the necessary applets based on the real system requirements. And as a single binary, all of the built-in applets share one ELF header and share all of the common functions. Besides those, compiler size optimization options like -Os and --gc-sections are also well supported.

Also, the last binary can be stripped with strip and sstrip, and the generated filesystem image can be compressed.

There's more...

We have discussed size optimization of ramdisk built with BusyBox. For the other parts of an embedded Linux system and the other methods, http://www.elinux.org/System_Size is a very good reference.

For the kernel parts, we can get more useful information from a project proposed by one of the authors of this book, at http://elinux.org/Work_on_Tiny_Linux_Kernel.