verrazano-narrows bridge
Sun Aug 27

Kernel Headers: What They Are and How to Install

If you are a Linux user or developer, you may have heard of the term kernel headers. But what exactly are they and why do you need them? In this article, we will explain what kernel headers are, how they work, and how to install them on different Linux distributions. We will also show you how to use them for compiling external kernel modules or device drivers.

What are Kernel Headers?

Kernel headers are files that contain the definitions of various data structures, constants, macros, and functions that are used by the Linux kernel. They are written in C language and have the .h extension. The kernel headers are essential for communicating with the kernel and accessing its features.

The kernel headers are not part of the kernel itself, but rather a separate package that can be installed on your system. They are usually located under /usr/src/linux-headers-$(uname -r), where $(uname -r) is the version of your running kernel.

The kernel headers are mainly used for two purposes:

  • To compile the kernel from source code. If you want to build your own custom kernel, you need the kernel headers to specify the configuration options and features that you want to include in your kernel.
  • To compile external kernel modules or device drivers. If you want to add support for new hardware devices or functionalities that are not included in the default kernel, you need the kernel headers to compile the code that interfaces with the kernel.

How to Install Kernel Headers in Ubuntu and Debian

If you are using Ubuntu or Debian, you can install the kernel headers using the apt package manager. The apt package manager will automatically download and install the matching kernel headers for your current kernel version.

To install the kernel headers, open a terminal and run the following command:

sudo apt update
sudo apt install linux-headers-$(uname -r)

This command will update your package index and install the linux- headers-$(uname -r) package, which contains the kernel headers for your running kernel.

You can verify that the kernel headers are installed by listing the contents of the /usr/src/linux-headers-$(uname -r) directory:

ls /usr/src/linux-headers-$(uname -r)

You should see several files and subdirectories, such as arch, include, Makefile, Module.symvers, etc.

How to Install Kernel Headers in Fedora and CentOS

If you are using Fedora or CentOS, you can install the kernel headers using the dnf or yum package manager. The dnf or yum package manager will also automatically download and install the matching kernel headers for your current kernel version.

To install the kernel headers, open a terminal and run the following command:

sudo dnf install kernel-headers

or

sudo yum install kernel-headers

This command will install the kernel-headers package, which contains the kernel headers for your running kernel.

You can verify that the kernel headers are installed by listing the contents of the /usr/src/kernels/$(uname -r) directory:

ls /usr/src/kernels/$(uname -r)

You should see similar files and subdirectories as in Ubuntu or Debian.

How to Use Kernel Headers for Compiling Kernel Modules

One of the most common uses of kernel headers is to compile external kernel modules or device drivers. A kernel module is a piece of code that can be loaded into or unloaded from the running kernel, without requiring a reboot. A device driver is a type of kernel module that provides an interface between the hardware device and the operating system.

To compile a kernel module, you need two things:

  • The source code of the module. This is usually a .c file that contains the code that implements the functionality of the module.
  • A Makefile that specifies how to compile and link the module. This is usually a file that contains some rules and variables that tell the compiler how to build the module.

For example, let’s say we want to compile a simple hello world module that prints a message when it is loaded or unloaded. The source code of the module, named hello.c, is as follows:

MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux Tutorial"); MODULE_DESCRIPTION("A simple hello world module"); MODULE_VERSION("0.1");

static int __init hello_init(void) { printk(KERN_INFO "Hello, world!\n"); return 0; }

static void __exit hello_exit(void) { printk(KERN_INFO "Goodbye, world!\n"); }

module_init(hello_init);
module_exit(hello_exit);

The Makefile for the module is as follows:

obj-m += hello.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

The Makefile uses the kernel headers to compile the module. The -C option tells the make command to change to the directory where the kernel headers are located, which is /lib/modules/$(shell uname -r)/build. The M=$(PWD) option tells the make command to use the current directory as the source directory for the module. The modules and clean targets are predefined targets that build and clean the module, respectively.

To compile the module, open a terminal and run the following command in the same directory where the hello.c and Makefile files are located:

make

This command will invoke the make command with the default target, which is all. The make command will then invoke another make command with the -C and M options, which will use the kernel headers to compile and link the module. The output of the command should look something like this:

make -C /lib/modules/5.14.0-1-amd64/build M=/home/linux-tutorial/hello modules
make[1]: Entering directory '/usr/src/linux-headers-5.14.0-1-amd64'
	CC [M]  /home/linux-tutorial/hello/hello.o
	MODPOST /home/linux-tutorial/hello/Module.symvers
	CC [M]  /home/linux-tutorial/hello/hello.mod.o
	LD [M]  /home/linux-tutorial/hello/hello.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.14.0-1-amd64'

If the compilation is successful, you should see a file named hello.ko in the same directory. This is the kernel module file that you can load or unload using the modprobe or insmod and rmmod commands.

To load the module, run the following command as root or with sudo:

sudo modprobe ./hello.ko

or

sudo insmod ./hello.ko

This command will insert the module into the running kernel. You should see a message in the kernel log that says “Hello, world!“. You can check the kernel log using the dmesg command:

dmesg | tail -1

The output should look something like this:

[  945.123456] Hello, world!

To unload the module, run the following command as root or with sudo:

sudo modprobe -r hello

or

sudo rmmod hello

This command will remove the module from the running kernel. You should see another message in the kernel log that says “Goodbye, world!“. You can check the kernel log again using the dmesg command:

dmesg | tail -1

The output should look something like this:

[  950.654321] Goodbye, world!

Conclusion

W have learned what kernel headers are, how they work, and how to install them on different Linux distributions. We have also seen how to use them for compiling external kernel modules or device drivers.

Kernel headers are an important tool for Linux users and developers who want to customize their kernel or add support for new hardware devices. They provide an interface between the kernel and user space programs, allowing them to communicate and access kernel features.