Linux內核中的初始化宏(_init、_exit等)

/************************************************************************************linux

*本文爲我的學習記錄,若有錯誤,歡迎指正。數據結構

*本文參考資料: 
函數

*        http://www.javashuo.com/article/p-kclgvccq-m.htmlpost

*        https://blog.csdn.net/qingkongyeyue/article/details/72935439學習

************************************************************************************/優化

在Linux內核的/kernel/include/linux/init.h文件中,定義了一些初始化宏。spa

1. 初始化宏的做用

初始化宏的做用主要有如下兩點:.net

                1)保證內核的初始化函數按照指定的順序來執行;code

                2)提升系統效率。blog

(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函數;
  • 若是不肯定需不須要添加宏,則不要添加。
相關文章
相關標籤/搜索