歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux設備驅動編程總結

Linux設備驅動編程總結

日期:2017/3/1 10:11:55   编辑:Linux編程

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

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

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

  1. #include <linux/kernel.h>
  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. MODULE_LICENSE("GPL"); //申明LICENSE,不寫編譯會有警告,所以還是寫了吧
  5. /*-----------------------------------------------------------------------------
  6. 函數名: hello_init
  7. 參數: void
  8. 返回值: <SPAN > </SPAN> int
  9. 描述: 模塊初始化函數,在安裝模塊時候執行
  10. *-----------------------------------------------------------------------------*/
  11. static int __init hello_init(void)
  12. {
  13. printk("hello world!--It is kernel speaking\n"); //類似於printf,是在內核中使用的打印函數
  14. return 0;
  15. }
  16. /*-----------------------------------------------------------------------------
  17. 函數名: hello_exit
  18. 參數: void
  19. 返回值: <SPAN > </SPAN>void
  20. 描述: 模塊退出函數,在安裝卸載時候執行
  21. *-----------------------------------------------------------------------------*/
  22. static void __exit hello_exit(void)
  23. {
  24. printk("Goodbye!Kernel\n");
  25. }
  26. module_init(hello_init);
  27. 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. CURRENT_PATH :=$(shell pwd)
  3. #VERSION_NUM :=$(shell uname -r)
  4. #LINUX_PATH :=/usr/src/linux-headers-$(VERSION_NUM)
  5. LINUX_PATH :=~/by700/linux-2.6.30-atmel9260
  6. all :
  7. make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules
  8. .PHONY :clean
  9. clean:
  10. 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