核心使用了大量不同的宏來標記具有不同作用的函數和資料結構。如宏__init 、__devinit 等。這些宏在include/linux/init.h 標頭檔中定義。編譯器通過這些宏可以把代碼最佳化放到合適的記憶體位置,以減少記憶體佔用和提高核心效率。
下面是一些常用的宏:
·
__init ,標記核心啟動時使用的初始化代碼,核心啟動完成後不再需要。以此標記的代碼位於.init.text 記憶體地區。它的宏定義是這樣的:
· #define _ _init _ _attribute_ _ ((_ _section_ _ (".text.init")))
·
__exit ,標記結束代碼,對於非模組無效。
·
__initdata ,標記核心啟動時使用的初始化資料結構,核心啟動完成後不再需要。以此標記的代碼位於.init.data 記憶體地區。
·
__devinit ,標記裝置初始化使用的代碼。
·
__devinitdata ,標記初始化裝置資料結構的函數。
·
__devexit ,標記移除裝置時使用的代碼。
·
xxx_initcall ,一系列的初始化代碼,按降序優先順序排列。
初始化代碼的記憶體結構
_init_begin -------------------
| .init.text | ---- __init
|-------------------|
| .init.data | ---- __initdata
_setup_start |-------------------|
| .init.setup | ---- __setup_param
__initcall_start |-------------------|
| .initcall1.init | ---- core_initcall
|-------------------|
| .initcall2.init | ---- postcore_initcall
|-------------------|
| .initcall3.init | ---- arch_initcall
|-------------------|
| .initcall4.init | ---- subsys_initcall
|-------------------|
| .initcall5.init | ---- fs_initcall
|-------------------|
| .initcall6.init | ---- device_initcall
|-------------------|
| .initcall7.init | ---- late_initcall
__initcall_end |-------------------|
| |
| ... ... ... |
| |
__init_end -------------------
初始化代碼的特點是:在系統啟動運行,且一旦運行後馬上退出記憶體,不再佔用記憶體。
對於驅動程式模組來說,這些最佳化標記使用的情況如下:
·
通過module_init() 和module_exit() 函數調用的函數就需要使用__init 和__exit 宏來標記。
·
pci_driver 資料結構不需標記。
·
probe() 和remove() 函數應該使用__devinit 和__devexit 標記,且只能標記probe() 和remove()
·
如果remove() 使用__devexit 標記,則在pci_driver 結構中要用__devexit_p(remove) 來引用remove() 函數。
·
如果你不確定需不需要添加最佳化宏則不要添加。
補充:例如,如果要在驅動中使用i2c或者spi匯流排,那麼他們的初始化常常會被賦值為subsys_initcall()等