Book Image

Mastering Embedded Linux Programming

By : Chris Simmonds
Book Image

Mastering Embedded Linux Programming

By: Chris Simmonds

Overview of this book

Mastering Embedded Linux Programming takes you through the product cycle and gives you an in-depth description of the components and options that are available at each stage. You will begin by learning about toolchains, bootloaders, the Linux kernel, and how to configure a root filesystem to create a basic working device. You will then learn how to use the two most commonly used build systems, Buildroot and Yocto, to speed up and simplify the development process. Building on this solid base, the next section considers how to make best use of raw NAND/NOR flash memory and managed flash eMMC chips, including mechanisms for increasing the lifetime of the devices and to perform reliable in-field updates. Next, you need to consider what techniques are best suited to writing applications for your device. We will then see how functions are split between processes and the usage of POSIX threads, which have a big impact on the responsiveness and performance of the final device The closing sections look at the techniques available to developers for profiling and tracing applications and kernel code using perf and ftrace.
Table of Contents (22 chapters)
Mastering Embedded Linux Programming
About the Author
About the Reviewers


An embedded system is a device with a computer inside that doesn't look like a computer. Washing machines, televisions, printers, cars, aircraft, and robots are all controlled by a computer of some sort, and in some cases, more than one. As these devices become more complex, and as our expectations of the things that we can do with them expand, the need for a powerful operating system to control them grows. Increasingly, Linux is the operating system of choice.

The power of Linux stems from its open source model, which encourages sharing of code. This means that software engineers from many backgrounds, and often employed by competing companies, can cooperate to create an operating system kernel that is up-to-date and tracks the development of the hardware. From this one code base, there is support from the largest super computers down to a wristwatch. Linux is only one component of the operating system. Many other components are needed to create a working system, from basic tools, such as a command shell, to graphical user interfaces, with web content and communicating with cloud services. The Linux kernel together with an extensive range of other open source components allow you to build a system that can function in a wide range of roles.

However, flexibility is a double-edged sword. While it gives a system designer a wide choice of solutions to a particular problem, it also presents the problem of knowing which are the best choices. The propose of this book is to describe in detail how to construct an embedded Linux system using free, open source projects to produce a robust, reliable, and efficient system. It is based on the experience of the author as a consultant and trainer over a period of many years, using examples to illustrate best practices.

What this book covers

Mastering Embedded Linux Programming is organized along the lines of the life cycle of a typical embedded Linux project. The first six chapters tell you what you need to know about how to set up the project and how a Linux system is put together, culminating in selecting an appropriate Linux build system. Next, comes the stage where certain key decisions must be made about the system architecture and design choices, including flash memory, device drivers, and the init system. Following this is the phase of writing applications to make use of the embedded platform you have built, and for which there are two chapters on processes, threads, and memory management. Finally, we come to the stage of debugging and optimizing the platform, which is discussed in chapters 12 and 13. The last chapter describes how to configure Linux for real-time applications.

Chapter 1, Starting Out, sets the scene by describing the choices available to the system designer at the start of a project.

Chapter 2, Learning About Toolchains, describes the components of a toolchain with an emphasis on cross-compiling. It describes where to get a toolchain and provides details on how to build one from the source code.

Chapter 3, All About Bootloaders, explains the role of the bootloader to initialize the hardware of the device and uses U-Boot and Bareboot as examples. It also describes the device tree, which is a means of encoding the hardware configuration, used in many embedded systems.

Chapter 4, Porting and Configuring the Kernel, provides information on how to select a Linux kernel for an embedded system and configure it for the hardware within the device. It also covers how to port Linux to the new hardware.

Chapter 5, Building a Root Filesystem, introduces the ideas behind the user space part of an embedded Linux implementation by means of a step-by-step guide on how to configure a root filesystem.

Chapter 6, Selecting a Build System, covers two embedded Linux build systems, which automate the steps described in the previous four chapters and conclude the first section of the book.

Chapter 7, Creating a Storage Strategy, discusses the challenges created by managing flash memory, including raw flash chips and embedded MMC or eMMC packages. It describes the filesystems that are applicable to each type of technology. It also covers techniques on how to update the device firmware in the field.

Chapter 8, Introducing Device Drivers, describes how kernel device drivers interact with the hardware with worked examples of a simple driver. It also describes the various ways of calling device drivers from the user space.

Chapter 9, Starting up - the init Program, shows how the first user space program, init, which starts the rest of the system. It describes the three versions of the init program, each suitable for a different group of embedded systems, with increasing complexity from BusyBox init to systemd.

Chapter 10, Learning About Processes and Threads, describes embedded systems from the point of view of the application programmer. This chapter looks at processes and threads, inter-process communication, and scheduling policies.

Chapter 11, Managing Memory, introduces the ideas behind virtual memory and how the address space is divided into memory mappings. It also covers how to detect memory that is being used and memory leaks.

Chapter 12, Debugging with GDB, shows you how to use the GNU debugger, GDB, to interactively debug both the user space and kernel code. It also describes the kernel debugger, kdb.

Chapter 13, Profiling and Tracing, covers the techniques available to measure the system performance, starting from whole system profiles and then zeroing in on particular areas where bottlenecks are causing poor performance. It also describes Valgrind as a tool to check the correctness of an application's use of thread synchronization and memory allocation.

Chapter 14, Real-time Programming, provides a detailed guide to real-time programming on Linux, including the configuration of the kernel and the real-time kernel patch, and also provides a description of tools to measure real-time latencies. It also covers information on how to reduce the number of page faults by locking the memory.

What you need for this book

The software used in this book is entirely open source. The versions used are, in most cases, the latest stable versions available at the time of writing. While I have tried to describe the main features in a manner that are not specific to a particular version, it is inevitable that the examples of commands contain some details that will not work with the later versions. I hope that the descriptions that accompany them are sufficiently informative so that you can apply the same principles to the later versions of the package.

There are two systems involved in creating an embedded system: the host system that is used to cross-compile the software and the target system on which it runs. For the host system, I have used Ubuntu 14.04, but most Linux distributions will work with little modification. In the same way, I had to choose a target system to represent an embedded system. I chose two: the BeagelBone Black and the QEMU CPU emulator, emulating an ARM target. The latter target means that you can try out the examples without having to invest in the hardware for an actual target device. At the same time, it should be possible to apply the examples to a wide range of targets with adaptations for specifics, such as device names and memory layout.

The versions of the main packages for the target are U-Boot 2015.07, Linux 4.1, Yocto Project 1.8 "Fido", and Buildroot 2015.08.

Who this book is for

This book is ideal for Linux developers and system programmers who are already familiar with embedded systems and who want to know how to create best-in-class devices. A basic understanding of C programming and experience with systems programming is needed.


In this book, you will find a number of text styles that distinguish between different kinds of information. Here are some examples of these styles and an explanation of their meaning.

Code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles are shown as follows: "We could use the stream I/O functions fopen(3), fread(3), and fclose(3)."

A block of code is set as follows:

static struct mtd_partition omap3beagle_nand_partitions[] = {
  /* All the partition sizes are listed in terms of NAND block size */
    .name        = "X-Loader",
    .offset      = 0,
    .size        = 4 * NAND_BLOCK_SIZE,
    .mask_flags  = MTD_WRITEABLE,  /* force read-only */

When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:

static struct mtd_partition omap3beagle_nand_partitions[] = {
  /* All the partition sizes are listed in terms of NAND block size */
    .name        = "X-Loader",
    .offset      = 0,
    .size         = 4 * NAND_BLOCK_SIZE,
    .mask_flags  = MTD_WRITEABLE,  /* force read-only */

Any command-line input or output is written as follows:

# flash_erase -j /dev/mtd6 0 0
# nandwrite /dev/mtd6 rootfs-sum.jffs2

New terms and important words are shown in bold. Words that you see on the screen, for example, in menus or dialog boxes, appear in the text like this: "The second line prints the message Please press Enter to activate this console on the console."


Warnings or important notes appear in a box like this.


Tips and tricks appear like this.

Reader feedback

Feedback from our readers is always welcome. Let us know what you think about this book—what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of.

To send us general feedback, simply e-mail , and mention the book's title in the subject of your message.

If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at

Customer support

Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.

Downloading the example code

You can download the example code files from your account at for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit and register to have the files e-mailed directly to you.


Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books—maybe a mistake in the text or the code—we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title.

To view the previously submitted errata, go to and enter the name of the book in the search field. The required information will appear under the Errata section.


Piracy of copyrighted material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy.

Please contact us at with a link to the suspected pirated material.

We appreciate your help in protecting our authors and our ability to bring you valuable content.


If you have a problem with any aspect of this book, you can contact us at , and we will do our best to address the problem.