新手,剛開始學linux下的驅動開發。前期看了本robert love《linux kernel development》,很多問題都沒有深究。
在學習ldd3時,遇到的第一個問題是編譯自己的內核,這個花費了一些工夫後終於搞定。
遇到的第二個問題就是這本書的第二章《構造和運行模塊》中的Makefile的問題。
現在初步有了自己的理解,記錄下來,供以後溫故知新,也方便有我相同疑問的朋友參考。
如有錯誤之處,請大家指出,共同進步,謝謝。
我的開發環境是fedora 13OS,自己下了2.6.35的Kernel源代碼樹,從新編譯,安裝了系統。
具體GNU工具的版本就不說了,都是fedora 13自帶的。看懂本文,可能需要有一點點makefile基礎,我也不是很精通:)
首先,將Makefile粘帖出來:
首先解釋下makefile中的幾點:
$(MAKE)--是指make。在內核樹的主makefile中,可以找到這個變量。
$(KERNELRELEASE)--KERNELRELEASE也是一個變量,可以在內核樹的主makefile中找到。
$(MAKE) -C $(KERNELDIR) --KERNELDIR在前面定義了,是指內核樹的根目錄。-C選項的作用是將當前的工作目錄轉移到你所指定的目錄,我們這裏指定爲內核樹的根目錄,/lib/modules/$(shell uname -r)/build指向的就是內核樹的根目錄,build是個軟鏈接。 uname -r是shell命令,顯示當前的內核版本號,我的是2.6.35.
M=$(PWD)--M=選項讓該makefile在構造modules目標之前,返回到當前目錄。一般這個makefile和驅動模塊的代碼在一起,就是返回到驅動模塊代碼所在的目錄。“M=” 選項的作用是,當用戶需要以某個內核爲基礎編譯一個外部模塊的話,需要在make modules 命令中加入“M=dir” ,程序會自動到你所指定的dir 目錄中查找模塊源碼,將其編譯,生成KO 文件。
modules--目標指向obj-m變量中設定的模塊。如果有多個源文件,obj-m := hello.o需要改一下,改如下:
接下來重點描述下我對makefile流程的理解,其實這個纔是我最花工夫的地方。
首先要搞明白一點,我的驅動代碼和這個makefile並不一定在內核樹根目錄下,實際上,我是在/home/xxx/src/下的。在shell裏,也是在這個目錄下執行的make命令。
執行make
首先檢查KERNERRELEASE變量,發現沒有定義,所以,走else,接下來定義了兩個變量KERNELDIR和PWD。
然後會走進default.
注意: 此時會因爲 -C $(KERNELDIR)進入內核樹根目錄,執行內核樹根目錄下的主makefile,這個makefile中有我們前面提到的兩個變量的聲明,KERNELRELEASE和MAKE。內核樹裏的主makefile會根據M=選項,執行M=選項指向的目錄處的驅動代碼的makefile。其實這是第二次讀這個makefile了。
然後根據M=選項指向的模塊目錄,再執行驅動代碼位置的makefile,也就是前面粘帖下來的makefile。你可能會有疑問,那這個makefile不是被讀了兩遍了嗎?是的。就是讀了兩遍,但是兩遍結果並不相同。因爲第二遍的時候,KERNELRELEASE 和MAKE變量有了定義。於是走了ifndef分支,obj-m有了定義,此時才真正的編譯內核模塊。編譯完模塊,會離開內核樹的目錄,回到M=選項指向的目錄。
一個標準的模塊編譯過程,makefile是要被讀兩次的。
採用這種makefile的好處是,既可以將驅動模塊放在內核樹裏面編譯(/usr/src/linux/driver/),也可以將驅動模塊放在內核樹外面,都可以編譯通過.
使用命令: make -n可以查看詳細的執行過程.
參考:
1.LDD3
2.http://www.embedu.org/Column/Column310.htm