五、指定與驅動相關的信息
雖然指定這些信息不是必須的,但一個完整的Linux驅動程序都會指定這些與驅動相關的信息。一般需要為Linux驅動程序指定如下信息。
1. 模塊作者:使用MODULE_AUTHOR宏指定。
2. 模塊描述:使用MODULE_DESCRIPTION宏指定。
3. 模塊別名:使用MODULE_ALIAS宏指定。
4. 開源協議:使用MODULE_LICENSE宏指定。
除瞭這些信息外,Linux驅動模塊自己還會包含一些信息。讀者可以執行下面的命令查看word_count.ko的信息。
# modinfo word_count.ko
執行上面的命令後,會輸出如圖6-6所示的信息。其中depends表示當前驅動模塊的依賴,word_count並沒有依賴什麼,因此該項為空。vermagic表示當前Linux驅動模塊在那個Linux內核版本下編譯的。
現在使用下面的代碼指定上述4種信息。一般會將這些代碼放在word_count.c文件的最後。
MODULE_AUTHOR("lining");
MODULE_DESCRIPTION("statistics of wordcount.");
MODULE_ALIAS("word count module.");
MODULE_LICENSE("GPL");
現在使用上一節的方法重新編譯word_count.c文件。然後再執行modinfo命令,就會顯示如圖6-7所示的信息。從圖6-7可以看出,上面的代碼設置的信息都包含在瞭word_count.ko文件中。
六、開源協議
雖然很多個人開發者或小公司並不太考慮開源協議的限制,但對於較大的公司如果違反開源協議,可能會有被起訴的風險。所以對有一定規模和影響力的公司使用開源軟件時一定要註意這些軟件使用的開源協議。
為瞭降低發佈Linux驅動的難度和安裝包尺寸,很多Linux驅動都是開放源代碼的。在Linux驅動源代碼中使用MODULE_LICENSE宏指定開源協議。例如,word_count驅動使用瞭GPL協議。那麼我們要編寫Linux'驅動程序應采取什麼協議呢?目前開源協議比較多。讀者可以到下面的頁面查看所有的開源協議。
http://www.opensource.org/licenses/alphabetical
下面將介紹最常用的5種開源協議的基本情況。這5種開源協議以及其他的開源協議的詳細情況請參閱Open SourceInitiative組織的相關頁面。
GPL協議
對於喜歡鉆研技術的程序員來說應該很喜歡GPL協議。因為GPL協議強迫使用該開源協議的軟件開源。例如,Linux內核就采用瞭GPL協議。GPL的出發點就是免費/開源。但與其他開源協議(如BSD、Apache Licence)不同的是GPL協議開源的更徹底。不僅要求采用GPL協議的軟件開源/免費,還要求其衍生代碼開源/免費。例如,A軟件采用瞭GPL協議,B軟件使用瞭A軟件,那麼B軟件也必須免費/開源。而其B軟件必須也采用GPL協議。C軟件又使用瞭B軟件,C軟件也必須開源/免費,當然,C軟件也必須采用GPL協議。這就是所謂的“傳染性”。這也是目前有很多Linux發行版及其他使用GPL協議的軟件開源的原因,
由於GPL協議嚴格要求使用瞭GPL協議的軟件產品必須使用GPL協議,而且必須開源/免費。對於商業軟件或者對代碼有保密要求的部門就非常不適合使用GPL協議發佈軟件,或引用基於GPL協議的類庫。為瞭滿足商業公司及保密的需要,在GPL協議的基礎上又出現瞭LGPL協議。
LGPL協議
LGPL主要是為類庫使用設計的開源協議。與GPL要求任何使用/修改/衍生的GPL類庫的的軟件必須采用GPL協議不同。LGPL 允許商業軟件通過類庫引用(link)方式使用LGPL類庫而不需要開源商業軟件的代碼。這使得采用LGPL協議的開源代碼可以被商業軟件作為類庫引用並發佈和銷售。
但是如果修改LGPL協議的代碼或者衍生,則所有修改的代碼,涉及修改部分的額外代碼和衍生的代碼都必須采用LGPL協議。因此LGPL協議的開源代碼很適合作為第三方類庫被商業軟件引用,但不適合希望以LGPL協議代碼為基礎,通過修改和衍生的方式做二次開發的商業軟件采用。
BSD協議
BSD開源協議是一個給於使用者很大自由的協議。基本上使用者可以“為所欲為”,可以自由的使用,修改源代碼,也可以將修改後的代碼作為開源或者專有軟件再發佈。但“為所欲為”的前提是當你發佈使用瞭BSD協議的代碼,或則以BSD協議代碼為基礎做二次開發自己的產品時,需要滿足如下3個條件。
1. 如果再發佈的產品中包含源代碼,則在源代碼中必須帶有原來代碼中的BSD協議。
2. 如果再發佈的隻是二進制類庫/軟件,則需要在類庫/軟件的文檔和版權聲明中包含原來代碼中的BSD協議。
3. 不可以用開源代碼的作者/機構名字和原來產品的名字做市場推廣。
BSD 協議鼓勵代碼共享,但需要尊重源代碼作者的著作權。BSD由於允許使用者修改和重新發佈代碼,也允許使用或在BSD代碼上開發商業軟件發佈和銷售,因此是對商業集成很友好的協議。而很多的公司企業在選用開源產品的時候都首選BSD協議,因為可以完全控制這些第三方的代碼,在必要的時候可以修改或者二次開發。
Apache Licence 2.0協議
Apache Licence是著名的非盈利開源組織Apache采用的協議。該協議和BSD類似,同樣鼓勵代碼共享和尊重原作者的著作權,同樣允許代碼修改,再發佈(作為開源或商業軟件)。需要滿足的條件也和BSD類似。
1. 需要給代碼的用戶一份Apache Licence
2. 如果你修改瞭代碼,需要在被修改的文件中說明。
3. 在延伸的代碼中(修改和由源代碼衍生的代碼中)需要帶有原來代碼中的協議,商標,專利聲明和其他原來作者規定需要包含的說明。
4. 如果再次發佈的產品中包含一個Notice文件,則在Notice文件中需要帶有Apache Licence。你可以在Notice中增加自己的許可,但不可以表現為Apache Licence。
Apache Licence也是對商業應用友好的許可。使用者也可以在需要的時候修改代碼來滿足需要並作為開源或商業產品發佈/銷售。
MIT協議
MIT是和BSD一樣限制寬松的許可協議,作者隻想保留版權,而無任何其他瞭限制.也就是說,你必須在你的發行版裡包含原許可協議的聲明,無論你是以二進制發佈的還是以源代碼發佈的。
七、註冊和註銷設備文件
本節將為word_count驅動建立一個設備文件,該設備文件的名稱是wordcount,位於/dev目錄中。設備文件與普通文件不同,不能使用IO函數建立,需要使用misc_register函數建立設備文件,使用misc_deregister函數註銷(移除)設備文件。這兩個函數的定義如下:
[cpp]
extern int misc_register(struct miscdevice * misc);
extern int misc_deregister(struct miscdevice*misc);
一般需要在初始化Linux驅動時建立設備文件,在卸載Linux驅動時刪除設備文件。而且設備文件還需要一個結構體(miscdevice)來描述與其相關的信息。miscdevice結構體中有一個重要的成員變量fops,用於描述設備文件在各種可觸發事件的函數指針。該成員變量的數據類型也是一個結構體file_operations。
本節需要修改word_count.c文件的word_count_init和word_count_exit函數,並定義一些宏和變量。修改部分的代碼如下:
[cpp]
// 定義設備文件名
#define DEVICE_NAME "wordcount"
// 描述與設備文件觸發的事件對應的回調函數指針
// owner:設備事件回調函數應用於哪些驅動模塊,THIS_MODULE表示應用於當前驅動模塊
static struct file_operations dev_fops =
{ .owner = THIS_MODULE};
// 描述設備文件的信息
// minor:次設備號 MISC_DYNAMIC_MINOR,:動態生成次設備號 name:設備文件名稱
// fops:file_operations結構體變量指針
static struct miscdevice misc =
{ .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME,.fops = &dev_fops };
// 初始化Linux驅動
static int word_count_init(void)
{
int ret;
// 建立設備文件
ret = misc_register(&misc);
// 輸出日志信息
printk("word_count_init_success\n");
return ret;
}
// 卸載Linux驅動
static void word_count_exit(void)
{
// 註銷(移除)設備文件
misc_deregister(&misc);
// 輸出日志信息
printk("word_init_exit_success\n");
}
編寫上面代碼需要註意如下幾點:
1. 設備文件由主設備號和次設備號描述。而使用misc_register函數隻能設置次設備號。主設備號統一設為10。主設備號為10的設備是Linux系統中擁有共同特性的簡單字符設備。這類設備稱為misc設備。如果讀者實現的驅動的功能並不復雜,可以考慮使用10作為其主設備號,而次設備號可以自己指定,也可以動態生成(需要指定MISC_DYNAMIC_MINOR常量)。因為采用這樣的方式可以使用misc_register和misc_deregister函數簡化註冊和註銷設備文件的步驟。在後面的章節會詳細介紹如何使用register_chrdev_region和alloc_chrdev_region函數同時指定主設備號和次設備號的方式註冊和註銷設備文件。
2. miscdevice.name變量的值就是設備文件的名稱。在本例中設備文件名稱為wordcount。
3. 雖然file_operations結構體中定義瞭多個回調函數指針變量,但本節並未初始化任何一個回調函數指針變量。隻初始化瞭file_operations.owner變量。如果該變量的值為module結構體,表示file_operations可被應用在這些由module指定的驅動模塊中。如果owner變量的值為THIS_MODULE,表示file_operations隻應用於當前驅動模塊。
4. 如果成功註冊瞭設備文件,misc_register函數返回非0的整數,如果註冊設備文件失敗,返回0。
5. 可能有的讀者註意到瞭。word_count.c中的所有函數、變量都聲明成瞭static。這是因為在C語言中用static聲明函數、變量等資源,系統會將這些函數和變量單獨放在內存的某一個區域,直到程序完全退出,否則這些資源不會被釋放。Linux驅動一旦裝載,除非手動卸載或關機,驅動會一直駐留內存,因此這些函數和變量資源會一直在內存中。也就是說多次調用這些資源不用再進行壓棧、出棧操作瞭。有利於提高驅動的運行效率。
現在重新編譯word_count.c文件並使用如下的命令安裝word_count驅動。
# insmod word_count.ko
如果word_count驅動已經被安裝,應先使用下面的命令下載word_count驅動,然後再使用上面的命令安裝word_count驅動。
# rmmod word_count
安裝完word_count驅動後,使用下面的命令查看/dev目錄中的設備。
# ls –a /dev
執行上面的命令後,會輸出如圖6-8所示的信息,其中多瞭一個wordcount文件(在白框中)。
如果想查看wordcount設備文件的主設備號和次設備號,可以使用如下的命令。
# ls –l /dev
執行上面的命令會輸出如圖6-9所示的信息,白框中的第一個數字是主設備號,第二個數字是從設備號。
使用下面的命令可獲顯示當期系統中有哪些主設備以及主設備號。
# cat /proc/devices
執行上面的命令後會輸出如圖6-10所示的信息,從中可以找到misc設備以及主設備編號10。