用c语言编写一个内核模块 helloworld
时间: 2025-08-06 14:04:27 浏览: 3
<think>我们使用C语言编写一个简单的Linux内核模块,它将在加载时打印"Hello, World!",在卸载时打印"Goodbye, World!"。
注意:内核模块的编写需要特定的环境(Linux系统,安装了对应版本的内核头文件)和编译方式(使用kbuild系统)。
以下是代码示例:
文件:hello_world.c
内容:
```c
#include <linux/init.h> // 包含宏定义,如 module_init, module_exit
#include <linux/module.h> // 包含内核模块相关的函数和宏,如 MODULE_LICENSE
// 模块加载函数
static int __init hello_init(void) {
printk(KERN_INFO "Hello, World!\n"); // 注意:内核中使用printk,而不是printf
return 0;
}
// 模块卸载函数
static void __exit hello_exit(void) {
printk(KERN_INFO "Goodbye, World!\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,内容如下(假设你的内核源代码目录在/lib/modules/$(shell uname -r)/build):
```makefile
obj-m := hello_world.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
```
编译和使用的步骤:
1. 将上述两个文件放在同一目录。
2. 执行 `make` 命令编译模块,生成 hello_world.ko 文件。
3. 加载模块:`sudo insmod hello_world.ko`,此时会打印"Hello, World!"(但不会显示在终端,而是记录在内核日志中)
4. 查看内核日志:`dmesg | tail -n 1` 可以看到输出。
5. 卸载模块:`sudo rmmod hello_world`,然后再次查看内核日志:`dmesg | tail -n 1` 可以看到"Goodbye, World!"。
注意:由于printk输出的日志级别,有时可能不会在控制台显示,但一定会在系统日志中记录(可通过dmesg查看)。
§§相关问题§§
1. 如何在内核模块中传递参数(例如在加载模块时指定打印的字符串)?
2. 在内核模块中,除了printk,还有哪些常用的日志输出函数或机制?
3. 编写内核模块时,为什么必须指定模块许可证(如GPL)?
4. 如何在内核模块中创建/proc文件接口与用户空间进行通信?
5. 如果多个源文件组成一个内核模块,Makefile应该如何编写?</think>以下是用C语言编写的Linux内核模块"Hello World"示例,包含模块加载/卸载函数和必要的Makefile:
### 1. 内核模块代码 (hello_world.c)
```c
#include <linux/module.h> // 所有内核模块必需的头文件
#include <linux/kernel.h> // 包含printk函数声明
#include <linux/init.h> // 包含__init和__exit宏
// 模块加载函数(insmod时调用)
static int __init hello_init(void)
{
printk(KERN_INFO "Hello, World! Kernel module loaded.\n");
return 0; // 返回0表示成功
}
// 模块卸载函数(rmmod时调用)
static void __exit hello_exit(void)
{
printk(KERN_INFO "Goodbye, World! Kernel module unloaded.\n");
}
// 注册模块加载/卸载函数
module_init(hello_init);
module_exit(hello_exit);
// 模块元信息
MODULE_LICENSE("GPL"); // 许可证声明(必需)
MODULE_AUTHOR("Your Name"); // 作者信息
MODULE_DESCRIPTION("Simple Hello World Kernel Module"); // 模块描述
MODULE_VERSION("0.1"); // 模块版本
```
### 2. Makefile (编译内核模块)
```makefile
obj-m := hello_world.o # 指定编译目标
# 内核源代码路径(根据你的系统修改)
KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
```
### 3. 编译和使用步骤
1. **编译模块**:
```bash
make
```
生成文件:`hello_world.ko` (内核模块)
2. **加载模块**:
```bash
sudo insmod hello_world.ko
```
3. **查看输出**:
```bash
dmesg | tail -n 2
# 输出示例:
# [ 1234.567890] Hello, World! Kernel module loaded.
```
4. **卸载模块**:
```bash
sudo rmmod hello_world
dmesg | tail -n 1
# 输出示例:
# [ 1234.678901] Goodbye, World! Kernel module unloaded.
```
### 关键点说明:
1. **printk vs printf**:内核模块使用`printk`(不是`printf`)输出日志
2. **__init/__exit宏**:标记初始化/清理函数,释放内存占用
3. **模块签名**:`MODULE_LICENSE`是必需声明(通常用GPL)
4. **内核API**:只能使用内核提供的API,不能使用标准C库
5. **安全考虑**:操作内核空间需要root权限(sudo)
阅读全文
相关推荐




















