歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux設備驅動編程總結

筆者搞設備驅動有一個多月了,也看了一些程序,前段時間一直很亂,沒有辦法總結,所以一直沒有寫文章,昨日熱的睡不著,腦袋中卻分外清晰,於是整理思路,將一個多月的學習心得總結出來,一方面供廣大嵌入式Linux開發者參考,一方面穩固自己的知識。

我將分為5篇文章去總結,這是第一篇,因為Linux中的驅動都是以模塊的方式加載到內核中的,所以學習模塊編程必須成為第一步。

各種官方的介紹此處略過,我們先來看一個最簡單的模塊實例:helloworld!

  1. #include <linux/kernel.h>   
  2. #include <linux/init.h>   
  3. #include <linux/module.h>   
  4.   
  5.   
  6. MODULE_LICENSE("GPL");      //申明LICENSE,不寫編譯會有警告,所以還是寫了吧   
  7.   
  8. /*----------------------------------------------------------------------------- 
  9.   函數名:      hello_init                                                                          
  10.                                                                                                           
  11.   參數:           void                                                                                                      
  12.   返回值:      <SPAN > </SPAN> int                                                                                                                                                                                                
  13.   描述:       模塊初始化函數,在安裝模塊時候執行                                                                                          
  14.                                                    
  15.  *-----------------------------------------------------------------------------*/  
  16. static int __init hello_init(void)    
  17. {  
  18.     printk("hello world!--It is kernel speaking\n");        //類似於printf,是在內核中使用的打印函數   
  19.     return 0;  
  20. }  
  21.   
  22. /*----------------------------------------------------------------------------- 
  23.   函數名:      hello_exit                                                                          
  24.                                                                                                           
  25.   參數:           void                                                                                                      
  26.   返回值:          <SPAN > </SPAN>void                                                                                                                                                                                                
  27.   描述:       模塊退出函數,在安裝卸載時候執行                                                                                          
  28.                                                    
  29.  *-----------------------------------------------------------------------------*/  
  30.   
  31. static void __exit hello_exit(void)   
  32. {  
  33.     printk("Goodbye!Kernel\n");  
  34. }  
  35.   
  36. module_init(hello_init);  
  37. module_exit(hello_exit);  

這個函數已經簡單的和helloworld一樣簡單清楚和可愛了,我只做幾點說明:

1.大家可以看到模塊函數沒有main函數,只有init函數,一般在模塊編譯好之後,會執行insmod命令,這是就會調用module_init函數中注冊的初始化函數,也就是hello_init函數!同樣在模塊用完之後,我們通常會執行rmmod以移除模塊,這時候就會調用module_exit中注冊的函數,也就是 hello_exit 函數。

2.__init和__exit,(注意是兩個下劃線)這個是兩個關鍵字,目的是告訴內核,在模塊init的時候開辟內存,在模塊退出的時候釋放內存,如果不加這兩個關鍵字,模塊卸載的時候就不會釋放內存,這就造成了內存的浪費。

Makefile:

有了程序,下面就要編譯程序了,模塊的編譯方法和編譯程序可不一樣,下面提供一個Makefile模板,這個時代已經不是從無到有的用手敲代碼了,而是在模板的基礎上改動,這樣才能提高效率:

  1. obj-m:=hello.o    
  2.   
  3. CURRENT_PATH :=$(shell pwd)  
  4. #VERSION_NUM  :=$(shell uname -r)   
  5. #LINUX_PATH   :=/usr/src/linux-headers-$(VERSION_NUM)   
  6. LINUX_PATH   :=~/by700/linux-2.6.30-atmel9260  
  7.   
  8. all :  
  9.     make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules   
  10.   
  11. .PHONY :clean  
  12. clean:  
  13.     rm -rf *.o *ko  

我也做幾點說明:

1.object -m :=hello.o,是要編譯的模塊的目標文件對應於hello.c,所以需要根據具體情況修改

2.對於這個模板我們第二個要修改的地方就是內核目錄,大家看到我用#把兩句話隱藏掉了,這個方便開啟PC和目標      板之間的切換:

對於PC端,一般編譯好的內核源代碼就放在我#號隱掉的目錄下,只要#號去掉,同時把第二個LINUX_PATH隱掉,就可以直接使用這個Makefile文件,這個不難,主要是目標板上的模塊,我調試了兩天才調試通

對於目標板(筆者的是at91)的芯片,LINUX_PATH這個目錄就需要調整了,因為我們在PC機上編譯目標板的內核代碼由讀者自己選定,我這個暫時就選定在如代碼中的目錄下。

特別注意,這個目錄一定要和目標板燒寫的鏡像是一致的,否則會出現內核和模塊不匹配的錯誤,筆者就是被這個錯誤改了內核代碼,結果越來越多錯誤,最後請教高手才解決的

我在這裡用的交叉編譯環境是:arm-angstrom-linux-gnueabi-

所以在執行的make的時候,要執行如下:make ARCH=arm CROSS_COMPILE=arm-angstrom-linux-gnueabi-

結果如下:

  1. root@at91sam9260ek:/mnt/hello# insmod hello.ko  
  2. hello world!--It is kernel speaking  
  3. root@at91sam9260ek:/mnt/hello# lsmod  
  4. Module                  Size  Used by    Not tainted  
  5. hello                   1120  0   
  6. root@at91sam9260ek:/mnt/hello# rmmod hello   
  7. Goodbye!Kernel  
  8. root@at91sam9260ek:/mnt/hello# lsmod  
  9. Module                  Size  Used by    Not tainted  
  10. root@at91sam9260ek:/mnt/hello#   

內核模塊可以加載的文件是.ko後綴名的!

Copyright © Linux教程網 All Rights Reserved