写一个 Linux 内核 hello world 模块
本文介绍如何一步步写一个 Linux 内核 hello world 模块.
内核模块分类
分为如下2类:
- Builtin modules 内置模块, 包含在 Linux image 里面
- External modules 外部模块, 可以随时加载/卸载的内核模块.
本文例子中的模块属于 外部模块.
Kernel Build System
更多 Linux 内核 Kbuild 系统的更多信息, 参看官方文档.
hello world 内核模块
创建一个 hello.c 文件. 源代码如下:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
static int __init hello_init(void)
{
printk(KERN_ALERT "hello world\n");
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_ALERT "goodbye\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_DESCRIPTION("my first module");
MODULE_LICENSE("free");
MODULE_AUTHOR("Eric Tian");
设置内核 build 环境
安装 Kernel header: 找到对应的包, 然后安装, 然后查看安装的包.
$ apt search linux-headers-$(uname -r)
$ sudo apt install linux-headers-$(uname -r)
$ file /lib/modules/$(uname -r)/build
/lib/modules/5.15.92/build: symbolic link to /home/supra/work/jammy/jammy-Ubuntu-5.15.0-70.77-test
Makefile
在 hello.c 相同的目录, 创建一个新文件 Makefile
. 内容如下, 缩进符号使用 tab
.
obj-m += hello.o
tag ?= `uname -r`
KDIR := /lib/modules/${tag}/build/
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
编译运行
$ make clean
$ make all
make -C /lib/modules/`uname -r`/build/ M=/home/supra/work/c/kernel modules
make[1]: Entering directory '/usr/src/linux-headers-5.15.0-76-generic'
CC [M] /home/supra/work/c/kernel/hello.o
MODPOST /home/supra/work/c/kernel/Module.symvers
CC [M] /home/supra/work/c/kernel/hello.mod.o
LD [M] /home/supra/work/c/kernel/hello.ko
BTF [M] /home/supra/work/c/kernel/hello.ko
Skipping BTF generation for /home/supra/work/c/kernel/hello.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-5.15.0-76-generic'
查看模块信息
$ modinfo hello.ko
modinfo hello.ko
filename: /home/supra/work/c/kernel/hello.ko
author: Eric Tian
license: free
description: my first module
srcversion: 01F8F75DC7D8708707AA062
depends:
retpoline: Y
name: hello
vermagic: 5.15.0-76-generic SMP mod_unload modversions
运行模块
$ sudo insmod hello.ko
insmod: ERROR: could not insert module hello.ko: Operation not permitted
虽然你用了 sudo
, 仍然得到上面的错误, 原因很可能是: Check if your system has secure boot enabled, which can prevent loading unsigned kernel modules. Disable secure boot in your system's BIOS/UEFI settings and try again.
解决上述问题后, 执行 insmod
然后通过 dmesg
查看日志信息.
$ sudo insmod hello.ko
$ sudo dmesg
[ 176.149789] hello: loading out-of-tree module taints kernel.
[ 176.149794] hello: module license 'free' taints kernel.
[ 176.149794] Disabling lock debugging due to kernel taint
[ 176.149815] hello: module verification failed: signature and/or required key missing - tainting kernel
[ 176.150529] hello world
查看加载的模块信息
$ lsmod | grep hello
Module Size Used by
hello 16384 0
$ sudo cat /proc/modules | grep hello
hello 16384 0 - Live 0xffffffffc0797000 (POE)
卸载模块 并查看 exit 日志
$ sudo rmmod hello
$ tail -n 10 /var/log/syslog
Jul 10 12:16:14 supra kernel: [ 596.219986] goodbye