网站主题颜色,网页设计板式网站,wordpress 12张表,各大网站收录入口在linux下编译可加载内核模块形成.ko文件的makefile中的核心语句是#xff1a;
$(MAKE) -C $(KERNEL_DIR) M(PWD) modules
这句是Makefile的规则#xff1a;这里的
$(MAKE)就相当于make;-C 选项的作用是指将当前工作目录转移到你所指定的位置#xff0c;一般都是内核源代… 在linux下编译可加载内核模块形成.ko文件的makefile中的核心语句是
$(MAKE) -C $(KERNEL_DIR) M(PWD) modules
这句是Makefile的规则这里的
$(MAKE)就相当于make;-C 选项的作用是指将当前工作目录转移到你所指定的位置一般都是内核源代码目录或者内核headers目录如/usr/include/linux-5.1.1-headers/类似的位置;-C $(KERNEL_DIR) 代表切换工作目录因为内核源码顶层的Makefile文件定义了伪目标 modules所以要先将工作目录切换到内核源码顶层 Makefile 所在位置“M”选项的作用是当用户需要以某个内核为基础编译一个外部模块的话需要在make modules 命令中加入“Mdir”程序会自动到你所指定的dir目录中查找模块源码将其编译生成KO文件。
注释这个是编译linux核外模块必备的makefile中的核心语句相当于先跳转到-C 指定的内核目录然后执行这个目录下的makefile MXXX modules这个有点不好理解一般都是在某个目录下执行makefile就行了这里是执行makefile MXXX modules相当于在当前系统内核根目录下执行make M XXX modules 进行XXX目录下的模块的编译编译成xx.ko.这样你的modules就可以在任何其他位置而不用必须在内核文件下面了。 例如
obj-m : hello.o
KVERSION: $(shell uname -r)all:$(MAKE) -C /lib/modules/$(KVERSION)/build M$(PWD) modules
clean:$(MAKE) -C /lib/modules/$(KVERSION)/build M$(PWD) clean---------------------------------------------------我是分割线------------------------------------------------------------
新的一般指2.6.18的内核版本内核模块编程中的make命令里有个M选项如下
make -C /lib/modules/$(shell uname -r )/build M $(PWD) modules
M$(PWD) 意思是返回到当前目录继续读入、执行当前的Makefile。 请参考从 2.4 到 2.6Linux 内核可装载模块机制的改变对设备驱动的影响-CSDN博客 这个M是kbuild的东西呢还是make本来自己就有的东西呢 按理说它是make的一个参数应该是make的东西但是make的doc里又找不到如果是kbuild里的东西它应该怎样来实现呢经查证这个M是内核根目录下的Makefile中使用的变量。M是makefile脚本中的一个变量variable:
Use make Mdir to specify directory of external module to build.
Old syntax make … SUBDIRS$PWD is still supported.
Setting the environment variable KBUILD_EXTMOD take precedence
ifdef SUBDIRSKBUILD_EXTMOD ? $(SUBDIRS)
endif
ifdef M //如果没有定义或赋值M此处M未定义undefinedifeq ($(origin M), “command line”) //如果定义了此句用来判断M是否从命令行来KBUILD_EXTMOD : $(M)endif
endif
以下是来自从 2.4 到 2.6Linux 内核可装载模块机制的改变对设备驱动的影响
清单32.6 内核模块的Makefile模板 #Makefile 2.6
ifneq ($(KERNELRELEASE),) #kbuild syntax. dependency relationshsip of files and target modules are listed here. mymodule-objs : file1.o file2.oobj-m : mymodule.o
elsePWD : $(shell pwd)KVER ? $(shell uname -r) KDIR:/lib/modules/$(KVER)/buildall: $(MAKE) -C $(KDIR ) M(PWD) modulesclean: rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
endif KERNELRELEASE是在内核源码的顶层Makefile中定义的一个变量在第一次读取执行此Makefile时KERNELRELEASE没有被定义 所以make将读取执行else之后的内容。
如果make的目标是clean直接执行clean操作然后结束。
当make的目标为all时-C $(KDIR ) 指明跳转到内核源码目录下读取那里的Makefile 解决M这个变量的定义问题和KERNELRELEASE变量赋值问题 M(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。当从内核源码目录返回时KERNELRELEASE已被被定义kbuild也被启动去解析kbuild语法的语句make将继续读取else之前的内容。else之前的内容为kbuild语法的语句, 指明模块源码中各文件的依赖关系以及要生成的目标模块名。mymodule-objs : file1.o file2.o表示mymoudule.o 由file1.o与file2.o 连接生成。obj-m : mymodule.o表示编译连接后将生成mymodule.o模块。
补充一点$(MAKE) -C ( KDIR ) M(PWD)“与”$(MAKE) -C (KDIR ) SUBDIRS(PWD)的作用是等效的后者是较老的使用方法。推荐使用M而不是SUBDIRS前者更明确。
通过以上比较可以看到从Makefile编写来看在2.6内核下内核模块编译不必定义复杂的CFLAGS而且模块中各文件依赖关系的表示简洁清晰。
针对要编译的模块的过程我猜测应该是1读取模块的makefile因为没有定义KERNELRELEASE变量所以先走else分支获得KDIR等信息2然后执行make all发现需要走make -C $(KDIR) M$(PWD) modules;3跳转到$(KDIR)目录读取该目录下的makefile得到KERNELRELEASE变量和M的定义和值以及其他所需要的内容4跳转到模块代码目录再读取makefile发现if已经成立走if5走make modules编译模块代码生成ko文件。至于为什么这样参考linux KBuild MakeFile介绍 之二-CSDN博客