Reader small image

You're reading from  Linux Kernel Programming - Second Edition

Product typeBook
Published inFeb 2024
PublisherPackt
ISBN-139781803232225
Edition2nd Edition
Tools
Right arrow
Author (1)
Kaiwan N. Billimoria
Kaiwan N. Billimoria
author image
Kaiwan N. Billimoria

Kaiwan N. Billimoria taught himself BASIC programming on his dad's IBM PC back in 1983. He was programming in C and Assembly on DOS until he discovered the joys of Unix, and by around 1997, Linux! Kaiwan has worked on many aspects of the Linux system programming stack, including Bash scripting, system programming in C, kernel internals, device drivers, and embedded Linux work. He has actively worked on several commercial/FOSS projects. His contributions include drivers to the mainline Linux OS and many smaller projects hosted on GitHub. His Linux passion feeds well into his passion for teaching these topics to engineers, which he has done for well over two decades now. He's also the author of Hands-On System Programming with Linux, Linux Kernel Programming (and its Part 2 book) and Linux Kernel Debugging. It doesn't hurt that he is a recreational ultrarunner too.
Read more about Kaiwan N. Billimoria

Right arrow

Writing Your First Kernel Module – Part 1

In the previous two chapters, you have learned the ins and outs of obtaining the kernel source tree and configuring and building it (for the x86). Now, welcome to your journey of learning about a fundamental aspect of Linux kernel development – the Loadable Kernel Module (LKM) framework – and how it is to be used by the module user or module author, who is typically a kernel or device driver programmer. This topic is rather vast and hence is split into two chapters – this one and the next.

In this chapter, we’ll begin by taking a quick look at the basics of the Linux kernel architecture, which will help us understand the LKM framework. Then, we’ll look into why kernel modules are useful and write, build, and run our simple Hello, world LKM. We’ll see how messages are written to the kernel log and understand and make use of the LKM Makefile. By the end of this chapter, you will have learned...

Technical requirements

If you have already carefully followed Online Chapter, Kernel Workspace Setup, then a portion of the technical prerequisites that follow will already be taken care of. (The first chapter also mentions various useful open-source tools and projects; I definitely recommend that you browse through it at least once.) For your convenience, we summarize some key points here.

To build and use an external (or out-of-tree) kernel module on a Linux distribution (or custom system), you need:

  • The kernel to be built with module support enabled (CONFIG_MODULES=y)
  • At a minimum, the following two components to be installed:
    • A toolchain: This includes the compiler, assembler, linker/loader, C library, and various other bits and pieces. If building for the local system, as we assume for now, then any modern Linux distribution will have a native toolchain pre-installed. If not, simply installing the GCC package for your distribution should be sufficient...

Understanding the kernel architecture – part 1

In this section, we begin to deepen our understanding of the Linux kernel. More specifically, here, we delve into what user and kernel spaces are, and the major subsystems and various components that make up the kernel. This information is dealt with at a higher level of abstraction for now and is deliberately kept brief. We shall delve a lot deeper into understanding the fabric of the kernel in Chapter 6, Kernel Internals Essentials – Processes and Threads.

User space and kernel space

Modern microprocessors support code execution at a minimum of two privilege levels. As a real-world example, the Intel/AMD x86[-64] family supports four privilege levels (they call them ring levels), the AArch32 (ARM-32) microprocessor family supports up to seven modes (ARM calls them execution modes; six are privileged and one is non-privileged), and the AArch64 (ARM-64/ARMv8) microprocessor family supports four exception levels ...

Exploring LKMs

A kernel module is a means to provide kernel-level functionality without resorting to working within the kernel source tree and the static kernel image.

Visualize a scenario where you have to add a support feature to the Linux kernel – perhaps a new device driver in order to use a certain hardware peripheral chip, a new filesystem, or a new I/O scheduler. One way to do this is obvious: update the kernel source tree with the new code, and configure, build, test, and deploy it.

Though this may seem straightforward, it’s a lot of work – every change in the code that we write, no matter how minor, will require us to rebuild the kernel image and then reboot the system in order to test it. There must be a cleaner, easier way; indeed, there is – the LKM framework!

The LKM framework

The LKM framework is a means to compile a piece of kernel code typically outside of the kernel source tree, often referred to as “out-of-tree&...

Writing our very first kernel module

When introducing a new programming language or topic, it has become a widely accepted computer programming tradition to mimic the original Hello, world program as the very first piece of code. I’m happy to follow this venerated tradition to introduce the Linux kernel’s powerful LKM framework. In this section, you will learn the steps to code a simple LKM. We explain the code in detail.

Introducing our Hello, world LKM C code

Without further ado, here is some simple Hello, world C code, implemented to abide by the Linux kernel’s LKM framework:

For reasons of readability and space constraints, only the key parts of most source code are displayed here. To view the complete source code (with all comments), build it, and run it, the entire source tree for this book is available in its GitHub repository here: https://github.com/PacktPublishing/Linux-Kernel-Programming_2E. We definitely expect you to clone it and...

Common operations on kernel modules

Now let’s delve into how exactly you can build, load, and unload a kernel module. Besides this, we’ll also walk through the basics regarding the tremendously useful printk() kernel API, details on listing the currently loaded kernel modules with lsmod, and a convenient script for automating some common tasks during kernel module development. So, let’s begin!

Building the kernel module

At the risk of repetition, we urge you to try out our simple Hello, world kernel module as an exercise (if you haven’t already done so)! To do so, we assume you have cloned this book’s GitHub repository (https://github.com/PacktPublishing/Linux-Kernel-Programming_2E) already. If not, please do so now (refer to the Technical requirements section for details).

Here, we show, step by step, how exactly you can build and then insert our very first kernel module into kernel memory. Again, a quick reminder: we have...

Understanding kernel logging and printk

There is still a lot to cover regarding the logging of kernel messages via the printk kernel API. This section delves into some of the details. It’s important for a budding kernel/driver developer like you to clearly understand these topics.

We saw earlier, in the A quick first look at the kernel printk() section, the essentials of using the kernel printk API’s functionality (have another look at it if you wish to). Here, we will explore a lot more with respect to the printk() API’s usage. Let’s get going!

Using the kernel memory ring buffer

The kernel log buffer is simply a memory buffer within the kernel virtual address space where the printk output is saved (logged). More technically, it’s the global __log_buf[] variable. Its definition in the kernel source is as follows:

kernel/printk/printk.c
#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
#define LOG_BUF_LEN_MAX (u32)(1 <<...

Understanding the basics of a kernel module Makefile

You may have noticed by now that we tend to follow a one-kernel-module-per-directory rule of sorts. Yes, that definitely helps keep things organized. So, let’s take our second kernel module, the ch4/printk_loglvl one. To build it, we just cd to its folder, type make, and (fingers crossed!) voilà, it’s done. We have the printk_loglevel.ko kernel module object freshly generated (which we can then apply insmod/rmmod to). But how exactly did it get built when we typed make? Explaining this is the purpose of this section.

First off, we do expect you to understand the basics regarding make and the Makefile. If not, don’t fret, we’ve provided links to check this out, within the Further reading section (in the paragraph labeled Makefiles: introductory stuff) of this chapter. . Check it out! (Link: https://github.com/PacktPublishing/Linux-Kernel-Programming_2E/blob/main/Further_Reading.md#chapter...

Summary

In this chapter, we covered the basics of Linux kernel architecture and the LKM framework. You learned what a kernel module is and why it’s useful. We then wrote a simple yet complete kernel module, a very basic Hello, world. We then delved further into how it works and the coding conventions to follow, along with the practicalities of how exactly to build, load, see the module listing, and unload it. Kernel logging with printk (and friends) was covered in some detail, along with explanations regarding the printk logging levels, controlling output to the console(s), and more. Details on how to emit pure debug-level kernel messages, and more importantly, an introduction to using the kernel’s dynamic debug feature were then dealt with. We then moved on to the rate-limiting printk, generating kernel messages from user space, standardizing its output format, and understanding the new printk indexing feature. We closed this chapter with an understanding of the basics...

Questions

As we conclude, here is a list of questions for you to test your knowledge regarding this chapter’s material: https://github.com/PacktPublishing/Linux-Kernel-Programming_2E/blob/main/questions/ch4_qs_assignments.txt. You will find some of the questions answered in the book’s GitHub repo: https://github.com/PacktPublishing/Linux-Kernel-Programming_2E/tree/master/solutions_to_assgn.

Further reading

To help you delve deeper into the subject with useful materials, we provide a rather detailed list of online references and links (and at times, even books) in a Further reading document in this book’s GitHub repository. The Further reading document is available here: https://github.com/PacktPublishing/Linux-Kernel-Programming_2E/blob/master/Further_Reading.md.

Leave a review!

Enjoying this book? Help readers like you by leaving an Amazon review. Scan the QR code below for a 20% discount code.

*Limited Offer

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Linux Kernel Programming - Second Edition
Published in: Feb 2024Publisher: PacktISBN-13: 9781803232225
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Kaiwan N. Billimoria

Kaiwan N. Billimoria taught himself BASIC programming on his dad's IBM PC back in 1983. He was programming in C and Assembly on DOS until he discovered the joys of Unix, and by around 1997, Linux! Kaiwan has worked on many aspects of the Linux system programming stack, including Bash scripting, system programming in C, kernel internals, device drivers, and embedded Linux work. He has actively worked on several commercial/FOSS projects. His contributions include drivers to the mainline Linux OS and many smaller projects hosted on GitHub. His Linux passion feeds well into his passion for teaching these topics to engineers, which he has done for well over two decades now. He's also the author of Hands-On System Programming with Linux, Linux Kernel Programming (and its Part 2 book) and Linux Kernel Debugging. It doesn't hurt that he is a recreational ultrarunner too.
Read more about Kaiwan N. Billimoria