[開發可統計單詞個數的Android驅動程序(1)](http://blog.csdn.net/nokiaguy/article/details/8523272)
**五、指定與驅動相關的信息**
雖然指定這些信息不是必須的,但一個完整的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函數注銷(移除)設備文件。這兩個函數的定義如下:
~~~
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函數,并定義一些宏和變量。修改部分的代碼如下:
~~~
// 定義設備文件名
#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。

[開發可統計單詞個數的Android驅動程序(3)](http://blog.csdn.net/nokiaguy/article/details/8608994)
本文節選至[《Android深度探索(卷1):HAL與驅動開發》](http://product.dangdang.com/main/product.aspx?product_id=23043311),接下來幾篇文章將詳細闡述如何開發ARM架構的Linux驅動,并分別利用android程序、NDK、可執行文件測試Linux驅動。可在ubuntu Linux、Android模擬器和S3C6410開發板(可以選購OK6410-A開發板,需要刷Android)