Book Image

Instant Optimizing Embedded Systems Using BusyBox

By : Wu Zhangjin, Cao Ziqiang
Book Image

Instant Optimizing Embedded Systems Using BusyBox

By: Wu Zhangjin, Cao Ziqiang

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)

Playing BusyBox on a virtual Android device (Intermediate)

This recipe uses a virtual Android device as the target platform that we just created to show the usage of BusyBox applets on an embedded platform. It will replace the Android toolbox mksh shell-based console with the more powerful BusyBox ash shell-based console. It starts a remote shell and a web service on it with BusyBox telnetd and httpd respectively.

The console based on BusyBox ash gives a more powerful shell environment. Not only can the applets be run on this console, but new shell scripts can also be written in such a shell environment.

The remote shell is useful for remote development and maintenance, and the web service is helpful for system monitoring. Both of them have common use cases in an embedded system.

Getting ready

At this stage, we aren't constructing a full bootable filesystem from scratch, but only using the BusyBox applets. So, for simplicity and ease of testing, we will install our compiled BusyBox binary and scripts into an existing Android ramdisk image.

At first, get a copy of the existing ramdisk.img; its path can be found at ~/.android/avd/busybox-avd.avd/hardware-qemu.ini; for example, adt-bundle-linux-x86_64/sdk/system-images/android-17/armeabi-v7a/ramdisk.img.

How to do it...

Three examples will be shown in this section to demonstrate the usage of the BusyBox applets on a virtual Android device.

  1. Replace the console based on Android mksh with the BusyBox ash console.

    Since the Android toolbox mksh shell is too lightweight, and the Android toolbox (the BusyBox-like toolset software) itself only provides a few of the applets, here it only shows us how to replace it with BusyBox ash. Start ash as the default console, and eventually build a more powerful shell environment.

    At first, decompress the original ramdisk image with the following steps:

    $ mv ramdisk.img ramdisk.img.gz
    $ gunzip ramdisk.img.gz
    $ mkdir ramdisk/ && cd ramdisk/
    $ cpio -i -F ../ramdisk.img

    Second, get a prebuilt BusyBox binary, busybox-armv7l, and put it into ramdisk/.

    $ wget
    $ cp busybox-armv7l ramdisk/

    Third, to install BusyBox at runtime, let's prepare a script and name it, and add it into ramdisk/.

    # -- Install busybox to /bin and start /bin/ash
    # remount root file system for read and write
    mount -o remount,rw /
    mkdir /bin
    chmod 0777 /bin/
    chmod 0777 /busybox-armv7l
    /busybox-armv7l --install -s /bin
    export SHELL=/bin/ash

    It remounts the root filesystem to be readable and writable and allows us to install BusyBox with ––install to /bin at runtime; lastly, it starts /bin/ash.

    $ cp ramdisk/

    Then start a service in init.rc to launch the previous script. Add a chmod command to make sure the previous script is executable.

    $ cd ramdisk/
    $ sed -i '/loglevel/a \\n    chmod 0777 /' init.rc

    Let the BusyBox applets be executed directly without the full path.

    Append the installation directory of the BusyBox applet, /bin, to the default PATH environment.

    $ sed -i -e "s#export PATH #export PATH /bin:#g" init.rc

    Replace the original console service with our console service that is based on ash.

    $ sed -i -e "s#service console.*#service console /bin/" init.rc

    Now back up the old ramdisk and recompress a new one.

    $ mv ramdisk.img ramdisk-backup.img
    $ cd ramdisk/
    $ find . | cpio -H newc -o | gzip -9 > ../ramdisk.img

    Lastly, run the emulator to start with our new ramdisk and with the BusyBox ash console.

    $ emulator @busybox-emulator -ramdisk ./ramdisk.img -shell -show-kernel
    / # echo $SHELL
    / # ls /bin
    [                  fold               mke2fs             setsid
    (truncated to fit in the text)
    / # which ls

    This code only lists a part of the applets installed. As we can see, the shell becomes /bin/ash. The applets are installed under /bin and the ls command is not the one provided by Android toolbox (/system/bin/ls) but the one (/bin/ls) installed by BusyBox. This indicates that we have successfully changed the console service to our own.

    The writing of new shell scripts under this shell environment based on ash will be introduced in the Enhancing system stability of an embedded (Android) system recipe.

  2. Start a remote shell with BusyBox telnetd:

    A real embedded system may have no serial port and adb and no local cable connected, but a network connection with Wi-Fi or 3G; accessing such systems may need a remote shell. As a lot of remote shells exist, such as SSH and Telnet, and since BusyBox doesn't provide an SSH daemon but telnetd, we use telnetd as an example here.

    Firstly, start the service on an emulator from a virtual serial port.

    / # echo "Hello, telnetd" > /data/telnetd.issue
    / # telnetd -f /data/telnetd.issue -p 3333
    / # ps | grep telnetd | grep -v grep
      731 0     0:00 telnetd -f /data/telnetd.issue -p 3333

    Second, build an emulated network connection. Android emulator does not provide a standalone full emulated network stack but a port-redirection-based network stack. In order to use the network service, the adb forward command should be used to enable the port redirection feature.

    Say you want to access the telnetd service seen previously. The remote tcp:3333

    of the emulator must be redirected to a port of our desktop development system (for example, tcp:3333) by running the following command:

    $ adb forward tcp:3333 tcp:3333

    Third, log in to the telnet service and issue the following command on the development system:

    $ telnet localhost 3333
    Hello, telnetd
    localhost login:

    It means it really logs in and gets a prompt, Hello, telnetd. However, without a user account and the password, we cannot log in. To avoid setting up a username and password, we can simply let telnetd spawn /bin/ash rather than /bin/login, then no login progress will be required. Let's start telnetd on the emulator as follows:

    / # telnetd -p 3333 -f /data/telnetd.issue -l /bin/ash

    Log in to the shell directly and experiment with our Android device remotely.

  3. Start a web server with httpd:

    Firstly, start httpd at /data/www, and create a simple HTML page on the target platform from a virtual serial port as follows:

    / # mkdir /data/www
    / # httpd -h /data/www -p 8080
    / # cat > /data/www/index.html
    <!doctype html><html><head><title>BusyBox</title></head><body><h1>Hello, Busybox Http Server Works.</h1></body></html>

    Second, just like telnetd, make a port redirection from the emulator to the development system.

    # adb forward tcp:8080 tcp:8080

    Lastly, let's access the httpd service with any modern web browser on our development system. Here we use the Chromium browser as an example:

How it works...

BusyBox applets cover the standard coreutils, console tools, e2fsprogs, procps, SELinux, editors, modutils, debianutils, login-utils, networking, sysklogd, util-linux, findutils, mailutils, printutils, and even a tiny shell interpreter. This recipe shows how to install some of them at runtime on an existing Android system and demonstrates the working of these three applets: ash, telnetd, and httpd.

To add more function for an embedded system, the other applets may also need to be configured via the configuration utility and used based on their full usage information with the --help command.

There's more...

In order to start the previously mentioned service during boot, we can add httpd and telnetd in the previous / script.

# Start httpd service
httpd -h /data/www -p 8080
# Start telnetd service
telnetd -f /data/telnetd.issue -p 3333 -l /bin/ash

To access them, we must also forward the remote ports to the development system as follows:

$ adb forward tcp:3333 tcp:3333
$ adb forward tcp:8080 tcp:8080