1. 编写第一个内核模块
任务目标
编写一个Linux内核模块,在加载时打印Hello, Kernel!,卸载时打印Goodbye, Kernel!,并掌握内核模块的基本框架、Makefile编写及编译加载流程。
环境依赖
- Linux系统(本案例以Ubuntu 22.04为例)
- 已安装的内核头文件:
sudo apt install linux-headers-$(uname -r) - 构建工具:
sudo apt install build-essential - 需要root权限执行模块加载/卸载命令
完整代码
创建文件hello.c:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int __init hello_init(void)
{
printk(KERN_INFO "Hello, Kernel!\n");
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "Goodbye, Kernel!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple Hello World kernel module");
创建同目录下Makefile:
obj-m := hello.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
编译与加载
- 在源码目录执行
make,生成hello.ko文件。 - 加载模块:
sudo insmod hello.ko - 查看加载日志:
dmesg | tail -5,应看到Hello, Kernel!。 - 卸载模块:
sudo rmmod hello - 再次查看日志:
dmesg | tail -5,应看到Goodbye, Kernel!。 - 清理编译产物:
make clean
验证判定标准
make无报错且生成hello.ko文件。insmod后dmesg输出包含Hello, Kernel!。rmmod后dmesg输出包含Goodbye, Kernel!。lsmod | grep hello在加载期间能列出模块,卸载后无输出。
常见问题
- 权限错误:
insmod/rmmod需root权限,使用sudo。 - 头文件缺失:编译报错找不到
linux/module.h时,安装对应内核头文件。 - 日志不显示:若
dmesg无输出,检查printk级别是否被控制台过滤,可尝试dmesg -n 8后重试。 - 模块已存在:重复加载报
File exists,先rmmod或重启。
本案例演示了内核模块的最小完整框架:module_init和module_exit宏注册入口/出口函数,printk输出日志,Makefile通过内核构建系统完成编译。掌握此流程后,后续案例将在此基础上扩展设备操作、文件接口等复杂功能。