(一)Linux代碼的重用c++
重用=靜態重用(將要重用的代碼放到其餘的文件的頭文件中聲明)+動態重用(使用另一個Linux驅動中的資源,例如函數、變量、宏等)函數
一、編譯是由多個文件組成的Linux驅動(靜態重用)指針
對於複雜的Linux驅動,須要使用多個源代碼文件存放不一樣的功能代碼,這樣作有利於代碼分類和管理,那麼就不得不編譯多個源代碼文件,最終生成.ko文件或編譯進Linux內核資源
下面,就介紹將3個.c文件分別編譯爲3個.o文件,並將這3個.o文件連接(link)成一個.ko文件——靜態重用get
假設C語言源代碼文件有main.c、fun.c、product.c、product.h,其中main.c是Linux驅動的主程序,在fun.c和product.c、product.h中定義和實現了在main.c中使用的函數,在main.c中經過extern關鍵字使用fun.c中的函數,經過包含product.h文件使用product.c文件中的函數編譯器
最關鍵一步就是編寫Makefile文件編譯
#Makefile變量
obj-m := multi_file_driver(文件所在目錄).omodule
multi_file_driver-y := main.o fun.o product.ofile
總之,c或c++ 語言中編譯多個源代碼文件時,若是a.c使用了b.c文件中的函數,須要在a.c文件中使用extern預先定義b.c中的函數,extern的做用是告訴編譯器該函數的函數名、參數個數、參數類型、返回值類型,等到將a.o和b.o連接成可執行文件或程序庫時,編譯器再到b.o中尋找函數的具體實現。除此以外,還可使用b.h文件定義b.c中的函數,而後在a.c中包含b.h文件。
二、Linux驅動模塊的依賴(動態重用)
在一個驅動模塊裏使用另外一個驅動模塊裏的被導出的符號(常量、變量、函數等)
下面,示例由兩個Linux驅動組成(symbol_producer和symbol_consumer),其中symbol_producer(symbol_producer.c文件)驅動的兩個函數(add和sub)和symbo_const常量以及result變量被導出,而在symbol_consumer(symbol_concumer.c文件)驅動中則使用了這4個被導出的符號。
symbol_producer.c 文件部分代碼以下://導出add函數
EXPORT_SYMBOL(add);
//導出result變量
EXPRORT_SYMBOL(result);
//導出sub函數,使用EXPROT_SYMBOL_GPL導出的符號
EXPORT_SYMBOL_GPL(sub);
//導出symbol_const常量
EXPORT_SYMBOL_GPL(symbol_const);
symbol_consumer.c文件中部分代碼以下:extern const char* symbol_const;//定義被導出的常量
extern int result;//定義被導出的變量
extern int add(int x1,int x2);//定義被導出的add函數
extern int sub(int x1,int x2);//定義被導出的sub函數
因爲有兩個Linux驅動,所以須要在Makefile文件中指定兩個Linux模塊,代碼以下:
#Makefile
obj-m := symbol_consumer.o
obj-m +=symbol_producer.o
注意:在安裝symbol_consumer以前,須要先安裝symbol_producer;卸載時順序正好相反。
(二)強行卸載Linux驅動
狀況1:初始化函數崩潰
因爲Linux驅動模塊的初始化函數進行了某些操做而崩潰,從而致使初始化函數沒法正常返回,這種狀況變現是當前Linux驅動模塊沒用被任何其餘的Linux驅動模塊使用,但卻顯示已經被應用了一次
這種狀況關鍵是引用計數器的值和引用者不一致。只須要將當前的Linux驅動模塊的引用計數器清零便可,修改計數器可使用下面兩個函數
//是module指向的Linux驅動模塊的引用計數器加1,成功返回1,失敗返回0
static inline int try_module_get(struct module *module);
//是module指向的Linux驅動模塊的引用計數器減1
extern void module_put(struct module *module);
狀況2:卸載函數被阻塞
在使用rmmod命令卸載Linux驅動時,系統會調用卸載函數,只有卸載函數成功返回時,Linux驅動纔會被卸載,若是卸載函數被阻塞,rmmod命令也會被阻塞,也就是說永遠不會執行到卸載Linux驅動模塊的代碼,這種狀況的表現是一執行rmmod命令就會停在那不動了,永遠也不會返回到系統的操做提示符
這種狀況的問題根源就是卸載函數,只要將原來的卸載函數替換成一個空的卸載函數便可
總之,二者狀況都要解決一個不可迴避的問題,就是要獲取表示要卸載的Linux驅動模塊的module結構體指針。