開發可統計單詞個數的Android驅動程式(1)
五、指定與驅動相關的資訊
雖然指定這些資訊不是必須的,但一個完整的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)
本文節選至《Android深度探索(卷1):HAL與驅動開發》, 接下來幾篇文章將詳細闡述如何開發ARM架構的Linux驅動,並分別利用android程式、NDK、可執行檔測試Linux驅動。可在ubuntu Linux、Android模擬器和S3C6410開發板(可以選購OK6410-A開發板,需要刷Android)