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