Linux中__init、__devinit等內(nèi)核優(yōu)化宏【轉(zhuǎn)】
轉(zhuǎn)自:https://blog.csdn.net/qingkongyeyue/article/details/72935439
https://blog.csdn.net/qingkongyeyue/article/details/72935439
內(nèi)核使用了大量不同的宏來標(biāo)記具有不同作用的函數(shù)和數(shù)據(jù)結(jié)構(gòu)叠赦。如宏__init 、__devinit 等革砸。這些宏在include/linux/init.h 頭文件中定義除秀。編譯器通過這些宏可以把代碼優(yōu)化放到合適的內(nèi)存位置,以減少內(nèi)存占用和提高內(nèi)核效率算利。
下面是一些常用的宏:
· __init
册踩,標(biāo)記內(nèi)核啟動時使用的初始化代碼,內(nèi)核啟動完成后不再需要效拭。以此標(biāo)記的代碼位于.init.text 內(nèi)存區(qū)域暂吉。它的宏定義是這樣的:
· #define _ _init _ _attribute_ _ ((_ _section_ _ (".text.init")))
· __exit
,標(biāo)記退出代碼缎患,對于非模塊無效慕的。如果編譯穩(wěn)定的話,exit函數(shù)將永遠(yuǎn)不會被調(diào)用挤渔。
#ifdef MODULE
#define __exit __attribute__ ((__section__(".exit.text")))
#else
#define __exit __attribute_used__ __attribute__((__section__(".exit.text")))
#endif
· __initdata
肮街,標(biāo)記內(nèi)核啟動時使用的初始化數(shù)據(jù)結(jié)構(gòu),內(nèi)核啟動完成后不再需要判导。以此標(biāo)記的代碼位于.init.data 內(nèi)存區(qū)域嫉父。
· __devinit
,標(biāo)記設(shè)備初始化使用的代碼眼刃。
· __devinitdata
绕辖,標(biāo)記初始化設(shè)備數(shù)據(jù)結(jié)構(gòu)的函數(shù)。
· __devexit
擂红,標(biāo)記移除設(shè)備時使用的代碼仪际。
· xxx_initcall
,一系列的初始化代碼,按降序優(yōu)先級排列弟头。
初始化代碼的特點是:在系統(tǒng)啟動運行,且一旦運行后馬上退出內(nèi)存涉茧,不再占用內(nèi)存赴恨。
- 所有標(biāo)識為
__init
的函數(shù),在鏈接的時候伴栓,都放在.init.text這個區(qū)域中伦连。在這個區(qū)域中,函數(shù)的擺放順序是和鏈接順序有關(guān)的钳垮,是不確定的惑淳。 - 所有的
__init
函數(shù)在區(qū)域.initcall.init中還保存了一份函數(shù)指針。在初始化時饺窿,內(nèi)核會通過這些函數(shù)指針調(diào) 用這些__init
函數(shù)歧焦,并在整個初始化完成后,釋放整個init區(qū)域 (包括.init.text, .initcall.init...)
注:這些函數(shù)在內(nèi)核初始化過程中的調(diào)用順序只和這里的函數(shù)指針順序有關(guān)肚医,和1中所述的這些函數(shù)代碼本身在.init.text區(qū)域中的順序無關(guān)绢馍。
對于驅(qū)動程序模塊來說,這些優(yōu)化標(biāo)記使用的情況如下:
· 通過module_init() 和module_exit() 函數(shù)調(diào)用的函數(shù)就需要使用__init
和 __exit
宏來標(biāo)記肠套。
· pci_driver 數(shù)據(jù)結(jié)構(gòu)不需標(biāo)記舰涌。
· probe() 和remove() 函數(shù)應(yīng)該使用 __devinit
和 __devexit
標(biāo)記,且只能標(biāo)記probe() 和remove()
· 如果remove() 使用 __devexit
標(biāo)記你稚,則在pci_driver 結(jié)構(gòu)中要用 __devexit_p(remove)
來引用remove() 函數(shù)瓷耙。
· 如果你不確定需不需要添加優(yōu)化宏則不要添加。