????????在linux下編譯可加載內(nèi)核模塊形成.ko文件的makefile中的核心語句是:
$(MAKE) -C?$(KERNEL_DIR) M=(PWD) modules
這句是Makefile的規(guī)則:這里的
- $(MAKE)就相當于make;
- -C 選項的作用是指將當前工作目錄轉(zhuǎn)移到你所指定的位置,一般都是內(nèi)核源代碼目錄或者內(nèi)核headers目錄,如/usr/include/linux-5.1.1-headers/類似的位置;-C $(KERNEL_DIR) 代表切換工作目錄,因為內(nèi)核源碼頂層的Makefile文件定義了偽目標 modules,所以要先將工作目錄切換到內(nèi)核源碼頂層 Makefile 所在位置;
- “M=”選項的作用是,當用戶需要以某個內(nèi)核為基礎(chǔ)編譯一個外部模塊的話,需要在make modules 命令中加入“M=dir”,程序會自動到你所指定的dir目錄中查找模塊源碼,將其編譯,生成KO文件。
注釋:這個是編譯linux核外模塊必備的makefile中的核心語句,相當于先跳轉(zhuǎn)到-C 指定的內(nèi)核目錄,然后執(zhí)行這個目錄下的makefile M=XXX modules(這個有點不好理解,一般都是在某個目錄下執(zhí)行makefile就行了,這里是執(zhí)行makefile M=XXX modules),相當于在當前系統(tǒng)內(nèi)核根目錄下執(zhí)行make M= XXX modules 進行XXX目錄下的模塊的編譯,編譯成xx.ko.這樣你的modules就可以在任何其他位置,而不用必須在內(nèi)核文件下面了。
例如:
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的內(nèi)核版本)內(nèi)核模塊編程中的make命令里有個M選項,如下:
make -C /lib/modules/$(shell uname -r )/build M = $(PWD) modules
M=$(PWD) 意思是返回到當前目錄繼續(xù)讀入、執(zhí)行當前的Makefile。
請參考:從 2.4 到 2.6:Linux 內(nèi)核可裝載模塊機制的改變對設(shè)備驅(qū)動的影響-CSDN博客
???????這個M是kbuild的東西呢,還是make本來自己就有的東西呢?
????????按理說,它是make的一個參數(shù),應(yīng)該是make的東西,但是make的doc里又找不到,如果是kbuild里的東西,它應(yīng)該怎樣來實現(xiàn)呢?經(jīng)查證這個M是內(nèi)核根目錄下的Makefile中使用的變量。M是makefile腳本中的一個變量(variable):
Use make M=dir 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 SUBDIRS
KBUILD_EXTMOD ?= $(SUBDIRS)
endif
ifdef M //如果沒有定義或賦值M,此處M未定義(undefined)
ifeq ("$(origin M)", “command line”) //如果定義了,此句用來判斷M是否從命令行來
KBUILD_EXTMOD := $(M)
endif
endif
以下是來自:從 2.4 到 2.6:Linux 內(nèi)核可裝載模塊機制的改變對設(shè)備驅(qū)動的影響
清單3:2.6 內(nèi)核模塊的Makefile模板
#Makefile 2.6
ifneq ($(KERNELRELEASE),)
#kbuild syntax. dependency relationshsip of files and target modules are listed here.
mymodule-objs := file1.o file2.o
obj-m := mymodule.o
else
PWD := $(shell pwd)
KVER ?=?$(shell uname -r) KDIR:=/lib/modules/$(KVER)/build
all:
$(MAKE) -C?$(KDIR ) M=(PWD) modules
clean: rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
endif
????????KERNELRELEASE是在內(nèi)核源碼的頂層Makefile中定義的一個變量,在第一次讀取執(zhí)行此Makefile時,KERNELRELEASE沒有被定義, 所以make將讀取執(zhí)行else之后的內(nèi)容。
如果make的目標是clean,直接執(zhí)行clean操作,然后結(jié)束。
當make的目標為all時,-C $(KDIR?) 指明跳轉(zhuǎn)到內(nèi)核源碼目錄下讀取那里的Makefile?(解決M這個變量的定義問題,和KERNELRELEASE變量賦值問題); M=(PWD) 表明然后返回到當前目錄繼續(xù)讀入、執(zhí)行當前的Makefile。當從內(nèi)核源碼目錄返回時,KERNELRELEASE已被被定義,kbuild也被啟動去解析kbuild語法的語句,make將繼續(xù)讀取else之前的內(nèi)容。else之前的內(nèi)容為kbuild語法的語句, 指明模塊源碼中各文件的依賴關(guān)系,以及要生成的目標模塊名。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內(nèi)核下,內(nèi)核模塊編譯不必定義復(fù)雜的CFLAGS,而且模塊中各文件依賴關(guān)系的表示簡潔清晰。文章來源:http://www.zghlxwxcb.cn/news/detail-757261.html
針對要編譯的模塊的過程,我猜測應(yīng)該是:(1)讀取模塊的makefile,因為沒有定義KERNELRELEASE變量,所以先走else分支,獲得KDIR等信息;(2)然后執(zhí)行make all,發(fā)現(xiàn)需要走make -C $(KDIR) M=$(PWD) modules;(3)跳轉(zhuǎn)到$(KDIR)目錄,讀取該目錄下的makefile,得到KERNELRELEASE變量和M的定義和值,以及其他所需要的內(nèi)容;(4)跳轉(zhuǎn)到模塊代碼目錄,再讀取makefile,發(fā)現(xiàn)if已經(jīng)成立,走if;(5)走make modules編譯模塊代碼生成ko文件。至于為什么這樣,參考linux KBuild MakeFile介紹 之二-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-757261.html
到了這里,關(guān)于編譯linux內(nèi)核模塊時的make -C M= modules的參數(shù)說明的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!