Linux Kernel Module (LKM)

Linux supports dynamic instertion and removal of code from the kernl while the system is up and running. The code what we add and remove at run time is called a kernel module

Once the LKM is loaded into the Linux kernel, you can start using new features and fucntionalities exposed by the kernel module without even restarting the device

LKM dynamically extends the functionality of the kernel by introducing new features to the kernel such as security, device drivers, file system drivers, system call

Support for LKM allows your embedded Linux systems to have only minimal base kernel image (less runtime storage) and optional device drivers and other features are supplied on demand via module insertion

Static(y)

When you build a Linux kernel, you can make your module statically linked to the kernel image (module becomes part of the final Linux kenrel image). This method increases the size of the final Linux kernel image. Since the module is 'built-in' into the Linux kernel image, you can not 'unload' the module. It occupies the memory permanently during run time

Dynamic(m)

When you build a Linux kernel, these modules are NOT build into the final kernel image, and rather there are compiled and linked separately to produce .ko files. You can dynamically load and unload these modules from the kernel using user space programs such as insmod, modprobe, rmmod

Kernel header vs user-space header

Since you write a kernel module that is going to be executed in kernel space, you should be using kernel headers, never include any user space library headers like C std library header files

No user space library is linked to the kernel module, most of the relevant kernel headers live in linux_source_bse/inlcude/linux/

Module initializtion function

Prototype: int fun_name(void);

Must return a value, 0 for success, nonzero means module initialization failed. So the module will not get loaded in the kernel

This is an entry point to your module (like main). This function will get called during boot time in the case of static modules

In the case of dynamic modules, this function will get called during module insertion

These should be one module initialization entry point in the module

Module clean-up function

Prototype: int fun_name(void);

This is an entry point when the module is removed

Since you can not remove static modules, clean-up function will get called only in the case of dynamic modules when it is removed using user space command such as rmmod

If you write a module and you are sure that it will always be statically linked with the kernel, then there is no need to implement this function

Even if your static module has a clean-up function, the kernel build system will remove it during the build if there is an __exit marker

Typically, you must do exact reserse operation what you had done in the module init function, undoing init function

Free memory which are requested in init function

De-init the devices or leave the device in the proper state

__init and __exit macros

__init and __exit makes sense only for static modules (built-in modules)

__init is a macro which will be translated into compiler directive, which instructs the compiler to put the code in .init section of the final ELF of linux kernel image

.init section will be freed from the memory by the kernel during boot time once all the initialization functions get executed

Since the built-in driver cannot be unloaded, its init function will not be called again until the next reboot, that's why there is no need to keep references to its init function anymore

so using __init macro is a technique, when used with a function, the kernel will free the code memory of that function after its execution

Similarly, you can use __initdata with variables that will be dropped after the initialization. __initdata, which works similarly to __init but for init variables rater than functions

You know that for built-in modules clean-up function is not required

So, when you use the __exit macro with a clean-up function, the kernel build system will exclude those functions during the build process itself

signal

Module entry points registration

module_init(my_kernel_module_init);

module_exit(ny_kernel_module_exit);

These are the macros used to register your module's init function and clean-up function with the kernel

Here module_init/module_exit is not a function, but a macro defined in linux/module.h

For example, module_init() will its parameter to the init entry point database of the kernel

module_eixt() will add its parameter to exit entry point database of the kernel

Module descripton

MODULE_LICENSE is macro used by the kernel module to announce its license type

If you a load module whose license parameter is non-GPL(General Public License), then kernel triggers warning of being tained. Its way of kernel letting the users and developers know its non-free license based module

The developer community may ignore the bug reports you submit after loading the proprietary licensed module

The declared module license is also used to decide whether a given module can have access to the small number of "GPL-only" symbols in the kernel

Go to linux/module.h to find out what are the allowed parameters which can be used with this macro to load the module without tainting the kernel

MODULE_INFO(name, "string_value);

You can see the module information by running the below command on the .ko file

arm-linux-gnueabihf-objdump -d -j .modifo file.ko

Building a kernel module

Kernel module can be built in 2 ways

1. Statically linked against the kernel image

2. Dynamically loadable

In most of the exercises in this course we will be writing and using dynamically loadable kernel modules

signal

In-tree and out of tree

Basically, out of tree means outside of the Linux kernel source tree

The module which are already part of the Linux kernel are called in-tree modules. (approved by the kernel developers and maintainers)

When you write a module separately (which is not approved and many by buggy), build and link it against the running kernel, then its called as out of the tree module.

Hence when you load an out of tree kernel module, kernel throws a warning message saying it got tainted.

Modules are built using "kbuild" which is the build system used by the Linux kernel

Modules must use "kbuild" to stay compatible with changes in the build infrastructure and to pick up the right flags to GCC

To build external modules, you must have a prebuilt kernel source available that contains the configuration and header files used in the build

This ensures that as the developer changes the kernel configuration, his custom driver is automatically rebuilt with the correct kernel configuration

Important note

When you are building out of tree (external) module, you need to have a complete and precompiled kernel source tree on your system

There reason is, modules are linked against object files found in the kernel source tree

You can not compile your module against one Linux kernel version and load it into the system, which is running kernel of different version. The module load may not be successful, and even if it is successful, you will encounter run time issues with the symbols

Thumb rule: "Have a precompiled Linux kernel source tree on your machine and build your module against that

Thre are two ways to obtain a prebuilt kernel version

1. Download kernel from your distributor and build it by yourself

2. Install the Linux-headers of the target Linux kernel

Command systax

make -C $KDIR M=$PWD [Targets]

-C $KDIR: The directory where the kernel source is located. "make" will actually change to the specified directory when executing and will change back when finished

M=$PWD: Informs kbuild that an external module is being built. The value given to "M" is the absolute path of the diretory where the external module (kbuild file) is located

[Target]

modules: The default target for external modules. It has the same functionality as if no target was specified

modules_install: Install the external module(s). The default locataion is /lib/modules/kernel_release/extra/, but a prefix may be added with INSTALL_MOD_PATH

clean: Remove all generated files in the module directory only

help: List the available targets for external modules

Creating a local Makefile

In the local makefile you should define a kbuild variable like below

obj-X:= module_name.o

Here obj-X is kbuild variable and "X" takes one of the below values

X = n, Do not compile the module

X = y, Compile the module and link with kernel image

X = m, Compile as dynamically loadable kernel module