Talk: Linux device drivers

(1) Implementing a Hello World module from scratch

Create a file named hello.c anywhere in your machine:

#include <linux/kernel.h>
#include <linux/module.h>

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

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

module_init(hello_init);
module_exit(hello_exit);

Now, in the same folder, create a file called Makefile with the following content:

obj-m   +=  hello.o

Compile your module (out of tree):

make -C /lib/modules/$(uname -r)/build M=$(pwd) hello.ko

Load your module to your kernel:

If you don't have sudo power

You can use virtme to be able to insert your module into the kernel. See appendix (A).

sudo insmod hello.ko

Check the logs:

sudo dmesg

Unload your module and check the logs again:

sudo rmmod hello
sudo dmesg

Now, click here to go to the exercises regarding char devices

(A) Inserting your module into your virtualized kernel with virtme

(1) Using the installed kernel

You have to acquire busybox beforehand, since the installed kernel probably needs a initramfs to boot.

cd <path> # where path is the directory you built your module
# Download busybox binary
curl -LO https://busybox.net/downloads/binaries/1.28.1-defconfig-multiarch/busybox-x86_64
# Give execution permission to busybox
chmod a+x busybox-x86_64

# run virtme with the installed kernel, with the downloaded busybox,
# giving read permission to your current dir to the virtualized environment
# and changing to the current directory
virtme-run --installed-kernel --busybox ./busybox-x86_64 --pwd

Now you should be in the virtualized environment.

insmod hello.ko # insert your module
rmmod hello.ko # remove your module
dmesg

(2) Using your compiled kernel

If you noticed, the Makefile showed previously uses your installed kernel to compile your module. It is infered by the path /lib/modules/$(shell uname -r)/build, which links to the kernel source.

If you try to insert this module, compiled for one version of Linux Kernel, into a kernel with other version, the insertion will fail.

So you just need to change to which kernel source the Makefile is pointing.

Let's modify this Makefile with your path:

MY_KERNEL_ROOT=<path_to_your_kernel_tree_root>

all:
        make -C $(MY_KERNEL_ROOT) M=$(PWD) modules

clean:
        make -C $(MY_KERNEL_ROOT) M=$(PWD) clean

Now run make. And run virtme:

cd <path> # where path is the directory where your Makefile is located
make
# run virtme with the custom kernel source tree,
# giving read permission to your current dir to the virtualized environment
# and changing to the current directory
virtme-run --kdir <path_to_your_kernel_tree_root> --pwd

Now you should be in the virtualized environment.

insmod hello.ko # insert your module
rmmod hello.ko # remove your module
dmesg

Done?

Even the bonus exercises?

We recomend watching this talk "O modelo de desenvolvimento de drivers do kernel Linux - Sergio Prado" (portuguese)

TODO: add a video in english

Try to understand the concepts and differences between a driver, a device, a bus, major and minor numbers in the context of the kernel.

\o/