[Linux Kernel] 撰寫 Hello, World module: The __init and __exit Macros (part 2).

再看此篇之前,可以先閱讀作者先前寫的:『[Linux Kernel Driver] 撰寫簡單 Hello, World module (part 1).』,今天要介紹 Driver 的 init module 區別,在 Kernel 2.4 版本,您可以自行定義 init 跟 cleanup 函式,他們不再被個別稱為 init_module()cleanup_module(),現在都使用 module_init()module_exit() 兩大巨集,這兩函式被定義在 linux/init.h 檔案裡面,所以在寫程式務必將其 include 喔,另外一個核心模組(MODULE_LICENSE),用於讓核心知道此模組遵守自由授權條款,若沒這項宣告,核心會跟您抱怨的喔,底下為範例:

#include  /* pr_info所需 include 檔案*/
#include 
#include  /* 所有 module 需要檔案*/
#include 

MODULE_DESCRIPTION("Hello World !!");
MODULE_AUTHOR("Bo-Yi Wu ");
MODULE_LICENSE("GPL");

static int __init hello_init(void)
{
    pr_info("Hello, world appleboy\n");
    pr_info("The process is \"%s\" (pid %i)\n", current->comm, current->pid);
    return 0;
}

static void __exit hello_exit(void)
{
    printk(KERN_INFO "Goodbye\n");
}

module_init(hello_init);
module_exit(hello_exit);
編譯過程,可以自行修改 Makefile,可以打開

kernel/android-2.6.29/drivers/i2c/chips/Makefile 參考範例,您會發現很多類似底下寫法:

obj-$(CONFIG_TWL4030_POWEROFF)  += twl4030-poweroff.o
obj-$(CONFIG_TWL4030_MADC)  += twl4030-madc.o
obj-$(CONFIG_RTC_X1205_I2C) += x1205.o
obj-$(CONFIG_SENSORS_BOSCH_BMA150)  += bma150.o
如果要編譯成 module 可以設定成

obj-m += bma150.o,編譯到 Kernel image,則會寫成 obj-y += bma150.o,然而 $(CONFIG_SENSORS_BOSCH_BMA150) 是從 make menuconfig 設定,當然為什麼 menuconfig 會出現此設定,那就要從 kernel/android-2.6.29/drivers/i2c/chips/Kconfig 裡面加入 CONFIG_SENSORS_BOSCH_BMA150 設定, 選好之後,觀看 Kernel 資料夾底下的 .config 內容,看到 CONFIG_SENSORS_BOSCH_BMA150=y,這樣就正確了。

What is different of __init and __exit? 在寫 G-Senser Driver 時候,您會發現 static int

__init BMA150_init(void) 跟 static void __exit BMA150_exit(void),跟平常寫 C 語言宣告函式不一樣吧,這兩個巨集分別有不同意義喔,當然也可以將 span style=“color:red”>__init 跟 __exit 拿掉,這不會影響 Driver 的編譯,但是會影響記憶體的優化,Driver 啟動時會呼叫 BMA150_init 函式,如果有加上 __init,當此 init function 執行完,會將記憶體 Release 給系統,這是針對 built-in 的方式才適用,如果是編譯成模組方式,則不會有此功能,然而 __exit 是 Driver 結束後會呼叫的 function,但是跟 __init 剛好功能相反,在 built-in 的 Kernel 映像檔並不會執行到 __exit,編譯成模組才會有釋放記憶體效果,這兩巨集可以參考 linux/init.h 檔案。


See also