如何通过GCC命令行将C文件编译为可modprobe加载的.ko内核模块
第一步:修正现有代码错误
你当前提供的代码不符合Linux内核模块开发规范,需要先调整为如下可编译版本:
#include <linux/module.h> #include <linux/platform_device.h> #include <linux/kernel.h> // 函数定义要放在使用前,避免未声明报错 static int my_driver_probe(struct platform_device *pdev) { printk("hello, world\n"); return 0; } static int my_driver_remove(struct platform_device *pdev) { printk("my driver removed\n"); return 0; } static struct platform_driver my_driver = { .probe = my_driver_probe, .remove = my_driver_remove, .driver = { .name = "my_test_driver", }, }; module_platform_driver(my_driver); // 必须声明LICENSE,否则加载会触发内核污染报错 MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Test hello world driver");
调整点说明:
- 移除手动声明的printk、platform_driver结构体,直接引入内核标准头文件
- 调整函数定义顺序,避免赋值时函数未声明
- 补充platform_driver的driver.name字段,这是平台驱动的必填参数
- 补充内核模块必须的元数据声明
第二步:编写编译Makefile
内核模块不能直接手写gcc命令编译,需要依赖内核源码树的Kbuild编译框架自动调用gcc处理参数,编写如下Makefile保存到代码同目录:
obj-m += my_driver.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
注意:Makefile中
all和clean下的命令行必须以Tab缩进,不能用空格,否则会编译报错。
第三步:执行编译
- 先安装对应内核版本的开发头文件:
- Debian/Ubuntu系:
apt install linux-headers-$(uname -r) - RHEL/CentOS系:
yum install kernel-devel-$(uname -r)
- Debian/Ubuntu系:
- 把修正后的代码保存为
my_driver.c,Makefile保存为Makefile(首字母大写) - 终端进入代码目录执行
make命令,编译完成后当前目录会生成my_driver.ko文件
加载验证
- 加载模块:
insmod ./my_driver.ko - 查看打印输出:
dmesg | tail即可看到hello, world的打印 - 卸载模块:
rmmod my_driver,卸载后再次执行dmesg | tail可看到卸载的打印内容
内容的提问来源于stack exchange,提问作者sashoalm
相关产品推荐
相关产品推荐

