天天看點

Helloworld子產品之核心makefile詳解

Hello World 子產品以及對應的核心makefile詳解

hello.c:
#include <linux/module.h> //所有子產品都需要的頭檔案
#include <linux/init.h>   // init&exit相關宏

MODULE_LICENSE("GPL");
MODULE_AUTHOR("feifei");
MODULE_DESCRIPTION("hello world module");

static int __init hello_init(void){
      printk(KERN_ERR "hello world");
      return 0;
}

static void __exit hello_exit(void){
      printk(KERN_EMERG "hello exit!");
}

module_init(hello_init);
module_exit(hello_exit);

/*注釋:這個子產品定義了兩個函數, 一個在子產品加載到核心時被調用( hello_init )以及一個在子產品被去除時被調用( hello_exit ).
moudle_init 和 module_exit 是比較特别的核心宏來指出這兩個函數的角色
宏 (MODULE_LICENSE) 是用來告知核心, 該子產品帶有一個自由的許可證; 沒有這樣的說明, 在子產品加載時核心會抱怨
printk 函數在 Linux 核心中定義并且對子產品可用;
它與标準 C 庫函數 printf 的行為相似. 核心需要它自己的列印函數, 因為它靠自己運作, 沒有 C 庫的幫助.
字串 KERN_EMERG 是消息的優先級,可以用 <1>,等對應的數字代替來字首于 printk 格式串之前. 注意如果用 KERN_ALERT ,之後要缺少一個逗号
*/

Makefile:
      
ifneq ($(KERNELRELEASE),)
obj-m :=hello.o
else
KDIR :=/lib/modules/&(shell uname -r)/build
all:
      make -C $(KDIR) M=$(PWD) modules
clean:
      rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif
~
/*注釋:
上面的這一行不是一個傳統的 makefile 的樣子,是kbuild makefile文法
obj-m :=hello.o表明有一個子產品要從目标檔案 hello.o 建立. 在從目标檔案建立後結果子產品命名為 hello.ko
擴充一點: 如果你有一個子產品名為 module.ko, 是來自 2 個源檔案( 姑且稱之為, file1.c 和 file2.c ), 正确的書寫應當是:
obj-m := module.o
module-objs := file1.o file2.o
make -C $(KDIR):這個指令開始是改變它的目錄到用 -C 選項提供的目錄下( 就是說, 你的核心源碼目錄 )
它在那裡會發現核心的頂層 makefile。
這個 M= 選項使 makefile 在試圖建立子產品目标前, 回到你的子產品源碼目錄。
M=$(PWD) 作為參數傳給Makefile,核心中的解釋是:make M=dir modules Make all modules in specified dir
目标, 是指在 obj-m 變量中發現的子產品清單, 在我們的例子裡設成了 hello.o
&(shell uname -r):是調用shell指令,在我系統上是2.6.18-92.el5,是以KDIR :=/lib/modules/&(shell uname -r)/build:
/lib/modules/2.6.18-92.el5/build/是核心源碼.
核心源碼Makefile中350行有關于KERNELRELEASE定義:
#KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)

下面,全面的解釋一下這個makefile的執行流程:
這個 makefile 在一次典型的建立中要被讀 2 次. 在第一次讀取執行此Makefile時,KERNELRELEASE沒有被定義,
是以make将讀取執行else之後的内容,如果make的目标是clean,直接執行clean操作,然後結束。當make的目标為all時,
-C $(KDIR)指明跳轉到核心源碼目錄下讀取那裡的Makefile;M=$(PWD) 表明然後傳回到目前目錄繼續讀入、
執行目前的Makefile。當從核心源碼目錄傳回時,KERNELRELEASE已被定義,kbuild也被啟動去解析kbuild文法的語句,
make将繼續讀取else之前的内容。else之前的内容為kbuild文法的語句,指明子產品源碼中各檔案的依賴關系,以及要生成的目标子產品名。
obj-m := hello.o表示編譯連接配接後将生成param.ko子產品。

這種建立子產品的機制你可能感覺笨拙模糊. 一旦你習慣了它, 但是, 你很可能會欣賞這種已經編排進核心建立系統的能力.
注意, 上面的不是一個完整的 makefile; 一個真正的 makefile 包含通常的目标類型來清除不要的檔案, 
安裝子產品等等. 一個完整的例子可以參考例子代碼目錄的 makefile.
*/
三。加載子產品
[root]# ls
hello.c hello.mod.c hello.o Module.markers Module.symvers
hello.ko hello.mod.o Makefile modules.order

root# insmod hello.ko
Hello, world
root# rmmod hello
hello exit!
           

繼續閱讀