0

我正在尝试通过遵循https://www.tldp.org/LDP/lkmpg/2.6/lkmpg.pdf并阅读 GNU make 手册来学习 linux 内核模块构建和 kbuild。

这是 Linux 内核模块编程指南中第一个示例 Hello-1 的 Makefile:

obj-m += hello-1.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

AFAIK,obj-m应该由 kbuild 阅读。但是根据 GNU Make 手册,我知道obj-m不应该导出。

除非通过显式请求,否则仅当变量最初在环境中定义或在命令行中设置,并且其名称仅包含字母、数字和下划线时,才会导出变量。某些 shell 无法处理由字母、数字和下划线以外的字符组成的环境变量名称。

https://www.gnu.org/software/make/manual/html_node/Variables_002fRecursion.html

obj-m最初既不是在环境中定义的,也不是在命令行中设置的。所以我希望它不应该导出到 target 的配方all。kbuild如何访问obj-m

4

1 回答 1

1

您的 makefile 调用 submake 并将M指向当前目录的 make 变量传递给它。使用该-C选项调用 submake,这样它就好像从指定目录(即内核源目录)调用一样运行。因此,使用的是具有自己的 makefile 的内核构建系统。多亏了这个M变量,内核makefiles知道他们可以在哪里找到你的makefile并将它包含在它的obj-m定义中。

注意:您显示的 makefile 可能应该使用条件进行一些修改,以便obj-m在 Linux 构建系统中只能看到变量定义。all否则,您的 makefile和clean目标与内核 makefile 中具有相同名称的目标之间存在冲突的风险。而且,正如 MadScientist 所指出的,使用make不是一个好主意;$(MAKE)更可取。你可能应该使用类似的东西:

ifeq ($(KERNELRELEASE),)
all:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
else
obj-m += hello-1.o
endif
于 2018-06-07T14:27:29.300 回答