Loadable Kernel Modules

14 Jun 2019

Devices have both device-independent and device-dependent code

There is special device driver code associated with each different device connected to the system:

  1. Device-Independent API
  2. Device-Dependent driver code
  3. Device Controller

Device Independent Part

  • a set of system calles that an application program can use to invoke I/O operations.
  • a particular device will respond to only a subset of these system calls.
    • A keyboard does not respont to write() system call.
  • POSIX set: open(), close(), read(), write(), lseek(), and ioctl()

Adding a New Device

When adding a new device, we write device-specific functions for each I/O system call. For each I/O system call, we add a new case clause to the switch statement in the device independent function call. After updating all dev_func_*(...) in the kernel, we need to compile the kernel. This is a big problem because we will need to recompile the kernel every time a new device or a new driver is added. Instead, we need a way to dynamically add new code into the OS kernel when a new device needs to be supported to avoid kernel recompilation. this is where Loadable Kernel Modules come into play.

Loadable Kernel Modules (LKMs)

A LKM is an object file that contains code to extend a running kernel. It offers an easy way to extend the functionality of the kernel without having to rebuild or recompile the kernel again. Using LKMs is a simple and efficient way to create programs that reside in the kernel and run in privileged mode. LKMs can be loaded and unloaded from the kernel on demand at runtime and most of the drivers are written as LKMs.

  • Use $ lsmod to list all the loaded kernel modules.

Requirements:

  • Must have a Linux kernel source tree to build your module.
  • Must be running the same kernel version you built your module with to run it.
  • Linux kernel object: .ko extension.

Kernel Module Components

A kernel module file has several typical components:

  • MODULE_AUTHOR(“name”)
  • MODULE_LICENSE(“GPL”)
    • License needs to be an open source license (GPL, BSD, etc.) or the kernel will be “tainted”.
    • A tainted kernel loses many abilities to run other open source modules and capabilities.

Key Operations:

  • int init_module(void)
    • This is called when the kernel loads the module.
    • Initialize everything here.
    • Typically this does one of the following:
      • Registers a handler for something with the kernel.
      • Replaces one of the kernel functions with its own code.
  • void cleanup_module(void)
    • This is called when the kernel unloads the module.
    • Free all the resources here.

Hello World Example

#include <linux/kernel.h>
#include <linux/module.h>
MODULE_AUTHOR("Me");
MODULE_LICENSE("GPL");

int init_module(void) {
  printk(KERN_ALERT "Hello World");
  return 0;
}

void cleanup_module(void) {
  printk(KERN_ALERT "Goodbye");
}

Where can we see the messages?

check dmesg or /var/log/system.log

Building the Kernel Module

  • Accompany the module with a one line GNU Makefile:
    • obj-m += hello.o
    • This assumes that the file name is hello.c
  • Execute the make command:
    • make -C <kernel-src> M='pwd' modules
    • This creates hello.ko
  • This assumes current directory is the module source.

Loading the Kernel Module

Use insmod to manually load the module. For example, execute:

sudo insmod helloworld.ko

insmod makes an init_module system call to load the LKM into kernel memory. The system call invokes the LKM’s initialization routine right after it loads the LKM. The LKM author sets up the initialization routine to call a kernel function that registers the subroutines that the LKM contains.

Unloading the Kernel Module

Run rmmod hello.ko. This will print the “Goodbye” message.

Kernel Module Dependencies

insmod/rmmod can be cumbersome because you have to manually enforce inter-module dependencies. modprobe automatically manages dependent modules.

  • Copy hello.ko into /lib/modules/<version>
  • Execute depmod
  • modprobe hello / modprobe -r hello

Dependent modules are automatically loaded/unloaded. depmod creates a Makefile-like dependency file based on the symbols it finds in the set of modules mentioned on the command line or from the directories specified in the configuration file. This dependency file is later used by modprobe to automatically load the correct module or stack of modules.

.ko files contain an additional .modinfo section where additional information about the module is kept (filename, license, dependencies…). The modinfo command retrieves that information: modinfo hello.ko.

Top