由module_init()宏想到的

 
一,前言
    在開發嵌入式Linux驅動程序時,我們通常使用module_init及module_exit宏來指定一個驅動程序的入口函數和出口函數。如果驅動模塊被編譯並鏈接至內核中,內核啓動的過程中會自動加載它。通過對這兩個宏定義的分析,可以寫出一個簡化的間接地調用函數的例子,其基本的方法是通過GNU GCC支持的__attribute__擴展功能將與入口函數地址鏈接至ELF文件中的特定的段區,並使用鏈接腳本導出該段區的地址,這樣就可以做到間接調用函數了。這可以視爲使用C語言開發軟件,模塊化的一個高級方法。
 
二,GNU GCC的鏈接腳本
    GNU binutils的文檔中指出,鏈接器ld中內嵌了一個默認的鏈接腳本,使用--version參數可以輸出該腳本,我們把它保存到internal-ldscript.ld:
 
    在修改這個鏈接腳本之前,我們要確定如何修改它;而在此之前,來讓我們先編寫一個用於測試的C代碼。
 
三,使用__attribute__將函數地址信息指定到特定的段區

    編寫的測試代碼如下:


 
    從圖中可以看到,在main函數中沒有直接地調用simple_add和simple_mul這兩個函數,而是訪問了兩個外部的結構體符號,即mfunc_info_start和mfunc_info_end,請注意這兩個是“符號”,而不是指針(指針是變量,它們兩個不是變量);同時,包含simple_add和simple_mul的函數地址和名稱的結構體被指定到了.data.mfunc段區。

 
四,修改鏈接腳本
    上圖C代碼中引用的兩個符號mfunc_info_start和mfunc_info_end需要在鏈接腳本中導出,修改後的鏈接腳本爲modified.ld,改動如下:
 
    至此,接下來我們就可以來編譯了。
 
五,編譯並測試
    編譯時需要指定鏈接腳本:
 

    從圖中可以看到,這樣間接地調用函數是可行的。當然,Linux驅動開發使用的宏比這個要複雜得多,還要解決一些模塊加載次序、依賴關係等,這就需要更深入的探究了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章