從Linux內核2.6開始,Linux內核的編譯採用Kbuild系統,這同過去的編譯系統有很大的不同,尤其對於Linux內核模塊的編譯。在新的系統下,Linux編譯系統會兩次掃描Linux的Makefile:首先編譯系統會讀取Linux內核頂層的Makefile,然後根據讀到的內容第二次讀取Kbuild的Makefile來編譯Linux內核。
Linux內核Makefile分類
- Kernel Makefile
- Kbuild Makefile
- ARCH Makefile
Kbuild Makefile
Kbuild Makefile的文件名不一定是Makefile,儘管推薦使用Makefile這個名字。大多的Kbuild文件的名字都是Makefile。爲了與其他Makefile文件相區別,你也可以指定Kbuild Makefile的名字爲Kbuild。而且如果“Makefile”和“Kbuild”文件同時存在,則Kbuild系統會使用“Kbuild”文件。
- 目標定義
-
obj-?
obj-? = $(target).o
target爲編譯對象的名字。如果沒有指定xxx-objs,這編譯這個對象需要的源文件就是$(target).c或$(target).s。如果指定了$(target)-objs,則編譯這個對象需要的源文件由$(target)-objs指定,並且不能有$(target).c或$(target).s文件。
- xxx-objs
- 嵌套編譯
- 編譯器選項
- ccflags-y, asflags-y and ldflags-y
有時候我們需要在內核源代碼數的外面編譯內核模塊,編譯的基本命令是:
我們可以把這個命令集成到Makefile裏,這樣我們就可以只輸入“make”命令就可以了。回想上一章的那個Makefile,它把Normal Makefile 和Kbuild Makefile集成到一個文件中了。爲了區別Kbuild Makefile 和Normal Makefile,這樣我們改寫Makefile爲如下形式,並且添加Kbuild Makefile - “Kbuild”。
##Makefile ifneq ($(KERNELRELEASE),) include "Kbuild" else KERNEL_DIR = /lib/modules/`uname -r`/build MODULEDIR := $(shell pwd) .PHONY: modules default: modules modules: make -C $(KERNEL_DIR) M=$(MODULEDIR) modules clean distclean: rm -f *.o *.mod.c .*.*.cmd *.ko rm -rf .tmp_versions endif |
## Kbuild MODULE_NAME = helloworld $(MODULE_NAME)-objs := hello.o obj-m := $(MODULE_NAME).o |
一般不需要在Makefile裏包含如下代碼,這樣寫完全是爲了兼容老版本的Kbuild系統。KERNELRELEASE變量在Kernel Makefile裏定義的,因此只有在第二次由Kbuild讀取這個Makefile文件時纔會解析到Kbuild的內容。
ifneq ($(KERNELRELEASE),) include "Kbuild" else ... endif |
外部頭文件
有時需要連接內核源代碼外部的系統頭文件,但Kbuild系統默認的系統頭文件都在內核源代碼內部,如何使用外部的頭文件呢?這個可以藉助於Kbuild系統的特殊規則:
- EXTRA_CFLAGS
EXTRA_CFLAGS += $(ext_include_path)
一般外部頭文件可能位於外部模塊源文件的目錄內,如何指定呢?這可以藉助$(src)或$(obj)
- $(src)/$(obj)
因此,我們修改Kbuild文件添加 EXTRA_CFLAGS 來包含外部頭文件儘管在這個驅動裏沒有引用外部系統頭文件:
## Kbuild MODULE_NAME = helloworld $(MODULE_NAME)-objs := hello.o EXTRA_CFLAGS := -I$(src)/include obj-m := $(MODULE_NAME).o |
後記
這裏我們詳細的介紹了Linux內核的Kbuild系統,相信你已經可以自如的寫自己的Kbuild Makefile了。現在開始,我們就可以寫帶有一些功能的驅動程序了。Linux裏的驅動程序可以分爲三類,字符設備驅動程序,塊設備驅動程序和網絡設備驅動程序。在後面的章節裏你會詳細的瞭解到這些驅動程序,同時可以瞭解到Linux內核裏用到的一些技術,如進程管理、內存管理、內核同步技術、內核時鐘等。