/************************************************************************************
*本文為個人學習記錄,如有錯誤,歡迎指正。
*本文參考資料:
************************************************************************************/
在Linux內核的/kernel/include/linux/init.h文件中,定義了一些初始化宏。
1. 初始化宏的作用
初始化宏的作用主要有以下兩點:
1)保證內核的初始化函數按照指定的順序來執行;
2)提高系統效率。
(1)保證內核的初始化函數按照指定的順序來執行
初始化宏的實質是段聲明。在內核鏈接的時候,被初始化宏修飾的函數將被鏈接至指定的段。內核初始化時,會按照相應段的優先級來順序執行初始化函數。
kernel將初始化要執行的init函數,分為7個級別:
1)core_initcall
2)postcore_initcall
3)arch_initcall
4)subsys_initcall
5)fs_iitcall
6)device_initcall
7)late_initcall
這7個級別優先級遞減,即先執行core_initcall, 最后執行late_initcall。通過使用初始化宏,gcc會將初始化代碼按下面的結構安排:
在內核初始化時,從__initcall_start到__initcall_end之間的initcall被一次執行。
(2)提高系統效率
初始化代碼的特點是,在系統啟動時運行,且一旦運行后馬上推出內存,不再占用內存。
2. 常用的宏
初始化宏的實質是段聲明。在內核鏈接的時候,被初始化宏修飾的函數將被鏈接至指定的段。
//標記內核啟動時所用的初始化代碼,內核啟動完成后就不再使用
#define __init __section(.init.text) __cold notrace
//標記內核啟動時所用的初始化數據結構,內核啟動完成后不再使用
#define __initdata __section(.init.data)
//標記模塊退出代碼,對非模塊無效
#define __exit __section(.exit.text) __exitused __cold
//標記設備初始化所用的代碼
#define __devinit __section(.devinit.text) __cold
//標記設備初始化所用的數據結構
#define __devinitdata __section(.devinit.data)
//標記設備移除時所用的代碼
#define __devexit __section(.devexit.text) __exitused __cold
對於驅動程序模塊來說,這些優化標記使用的情況如下:
module_init, module_exit函數所調用的函數,需要分別用__init和__exit來標記;
driver數據結構不需要標記;
probe和remove函數用__devinit和__devexit來標記;
如果remove使用__devexit標記,則在drvier結構中要用__devexit_p(remove)來引用remove函數;
如果不確定需不需要添加宏,則不要添加。