Linux内核驱动模块开发Makefile实例解析

2023年 2月 3日 92点热度 0人点赞

原文地址: linux 内核驱动模块开发 makefile 实例解析_leon1741 的博客-CSDN 博客

昨天整理了一篇关于 Linux 内核驱动模块的开发介绍入门, 其中介绍了一些关于驱动模块的基本开发步骤, 不过面广而不深, 很多细节都没有涉及到, 其中就包括如何编写驱动模块的 Makefile. 那么, 今天我们就来聊一聊这个话题.

以下是摘自网络上的一个经典的 Linux 设备驱动的 Makefile 文件, 以及详细的内容解释. 此文件可以完成对大部分驱动的编译, 使用时只需要稍加修改就可以了.

$(warning KERNELRELEASE=$(KERNELRELEASE))

ifeq ($(KERNELRELEASE),)

# 内核路径
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
MYMOD := hello

modules:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:
    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*

.PHONY: modules modules_install clean

else
    obj-m := $(MYMOD).o
endif

下面来依次介绍 Makefile 文件中的各行语句的作用:

变量定义. 首先, 如果你在模块的源代码目录下执行 make, 此时, 宏 KERNELRELEASE 是没有定义的, 所以会执行 ifeq 下面的内容, 分别将以下变量进行赋值:

  • KERNELDIR: 这个变量是用来存放内核源码的路径的, 在 Makefile 中我们可以看到有两个 KERNELDIR, 一个是用来保存标准的内核源码所在的路径的, 一个是用来保存当前正在运行的 ubuntu 系统自己的内核源码路径. 如果你的驱动要在开发板上运行, 那么你的 Makefile 中 KERNELDIR 就要选择标准的内核源码路径, 如果你的驱动只想在你的 ubuntu 上测试, 那么选用当前正在运行的 ubuntu 系统自己的内核源码路径就可以了.
  • PWD: 这个变量是用来保存你当前的驱动源码所在的路径的.
  • MYMOD: 这个变量是用来保存你的模块的名字的, 在编译时会寻找 $(MYMOD).c 进行编译, 最终也会生成一个 $(MYMOD).ko, 所以要编译你自己的模块你需要修改这个 MYMOD.

编译规则. 由于 make 后面没有目标, 所以 make 会在 Makefile 中的第一个不是以 . 开头的目标作为默认的目标执行. 于是 modules 成为 make 的目标. 也就是执行下面的规则:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

这条规则展开之后就是:

make –C /home/linux/linux3.14/M=/home/linux/test/ modules

其中:

  • -C 表示到存放内核的目录执行其 Makefile, 在执行过程中会定义 KERNELRELEASE, KERNELRELEASE 在内核顶层 Makefile 中第 396 行:
    KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
  • 2> 代表错误重定向, 当前面出现错误信息 (cat 不到) 时不会在终端上打印, 而是重定向到一个空文件中 (黑洞, 看不到), 如果没有错误就赋值给 KERNELRELEASE, 并且不会重定向.
  • M= 选项的作用是, 当用户需要以某个内核为基础编译一个外部模块的话, 需要在 make modules 命令中加入 M=dir, 程序会自动到你所指定的 dir 目录中查找模块源码, 将其编译, 生成 .ko 文件.

当执行完这条规则之后 Makefile 就会执行 else 分支: obj-m= hello.o, 执行这条规则就会将 hello.c 编译成 hello.o, 最终编译成模块 hello.ko.

.PHONY 这是一个特殊目标名称, .PHONY 目标的具体意思是如果在 Makefile 的工作目录中有名如: modules, modules_install, clean 等文件时命令会出错, 它是防止这出错的方式.

最后, 再贴上我自己项目中改进后的 Makefile 的源码, 以供参考:

KERNEL_DIR=$(TOP_DIR)/platform/kernel
DRVNAME=mydrv_gpio
PWD=$(shell pwd)
obj-m+=$(DRVNAME).o
$(DRVNAME)-objs := $(DRVNAME).o

build:
    @echo $(KERNEL_DIR)
    $(MAKE) -C $(KERNEL_DIR) M=$(PWD)

install: build
    cp $(DRVNAME).ko $(COM_INSTALL_YXAON_DIR)/user/yxko

clean:
    @rm -rf *.o *.ko .*.cmd *.mod.c *.order *.symvers .tmp_versions *~

rainbow

这个人很懒,什么都没留下

文章评论