You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用单个Makefile编译Linux可加载内核模块与用户应用程序遇阻求助

刚入坑Linux驱动开发确实容易在Makefile上栽跟头,我来帮你搞定这个用单个Makefile同时编译用户态程序和内核模块的问题!

先看看你给出的Makefile片段,问题很明显:你只配置了内核模块的编译框架,但没添加用户态应用的编译规则,而且命令还没写完($(KERNE...应该是$(KERNELDIR)对吧?)。

下面是我帮你调整后的完整Makefile,直接能用,我会给你拆解开讲清楚每个部分:

# 指定内核源码的构建目录,这是标准路径
KERNELDIR = /lib/modules/$(shell uname -r)/build
# 声明要编译的内核模块对象(你的驱动源文件应该是deviceJino.c吧?)
obj-m := deviceJino.o
# 获取当前工作目录的绝对路径
PWD := $(shell pwd)
# 定义你的用户态应用程序目标名(替换成你实际的用户态程序文件名,不用带.c)
APP := user_test_app

# 默认执行目标:先编译内核模块,再编译用户态程序
default: module app

# 编译内核模块的规则,这是内核模块编译的标准写法
module:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

# 编译用户态程序的规则,基础gcc编译命令,有额外依赖可以加参数
app:
	gcc -o $(APP) $(APP).c

# 清理规则:同时清掉内核模块的编译产物和用户态可执行文件
clean:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
	rm -f $(APP)

关键细节说明:

  • default: module app:当你直接敲make时,会按顺序执行moduleapp两个目标,先搞定驱动模块,再编译用户态程序。
  • 内核模块编译命令$(MAKE) -C $(KERNELDIR) M=$(PWD) modules-C是让make跳转到内核源码目录执行构建脚本,M=$(PWD)是告诉内核构建系统回到当前目录找你的驱动源码,modules是内核构建系统的标准目标,用来编译模块。
  • 用户态编译部分:如果你的用户态程序用到了特殊库(比如需要操作设备文件时用到的额外依赖),可以在gcc命令后加参数,比如gcc -o $(APP) $(APP).c -lpthread(如果用到线程的话)。
  • clean目标:一次性清理所有编译垃圾,包括内核模块生成的.ko.mod.c.o这些文件,还有用户态的可执行程序。

额外注意事项:

  1. 确保你的用户态程序文件名和Makefile里的APP变量对应,比如你的用户态代码是test_device.c,那APP := test_device
  2. 编译内核模块不需要root权限,但加载模块(sudo insmod deviceJino.ko)和操作设备文件可能需要。
  3. 如果编译时提示找不到内核头文件,先安装对应版本的内核头文件包:
    sudo apt install linux-headers-$(uname -r)  # Debian/Ubuntu系
    # 红帽/ CentOS系用:sudo dnf install kernel-devel-$(uname -r)
    

内容的提问来源于stack exchange,提问作者Jino

火山引擎 最新活动