內核使用了大量不同的宏來標記具有不同作用的函數和數據結構。如宏__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() 函數。
· 如果你不確定需不需要添加優化宏則不要添加。