關注「技術簡說」,一步一步教你開發linux內核和驅動。
hello world!是廣大程式設計師入門一門新語言的第一步。
今天,我們來看一個hello驅動,希望這是大家入門linux內核驅動的良好開局。
我的環境是ubuntu 14.04,內核版本 4.4.0-31-generic,本節我會開發一個基於ubuntu 14.04下的最簡單的hello驅動,帶大家領略驅動的魅力。
開發linux內核驅動需要以下4個步驟:
驅動代碼如下 helloDev.c,這是一個最小、最簡單的驅動,我去掉了其他的不相干代碼,儘量讓大家能了解驅動本身。
include <linux/moduleparam.h>include <linux/fs.h>include <linux/poll.h>include <linux/slab.h>define OK (0)34;hello_open\r\n&34;hello_write\r\n&34;hello_read\r\n&34;helloworld&34;register_chrdev_region ok \n&34;register_chrdev_region error n&34; hello driver init \n&34;GPL&KDIR := /lib/modules/`uname -r`/buildall: make -C $(KDIR) M=$(PWD)clean: rm -rf *.o *.ko *.mod.c *.symvers *.c~ *~endif
linux應用層程序在編譯的時候,需要連結c運行時庫和glibc庫。那驅動需不需要呢?
驅動也需要,但是驅動不能連結和使用應用層的任何lib庫,驅動需要引用內核的頭文件和函數。所以,編譯的時候需要指定內核源碼的地址。為了開發方便,也可以安裝內核開發包,之後引用這個內核開發包的目錄也可以。本例為:/lib/modules/4.4.0-31-generic/build
驅動文件和Makefile都有了,那麼接下來就可以編譯和加載驅動了!
在驅動目錄下,執行make進行編譯:
編譯出來的驅動文件,名稱為:helloDev.ko
接下來把這個驅動加載到內核:
helloDriver加載成功,列印出了:
[11837.379638] register_chrdev_region ok
[11837.379642] hello driver init
可見,執行insmod的時候,驅動文件裡的hello_init被調用了。
那驅動文件裡的hello_exit什麼時候會被調用呢?
可能聰明的你已經猜到了,那就是執行 rmmod helloDev.ko的時候。
本節來看驅動的測試。
我們需要編寫一個應用層的程序來對hello驅動進行測試:(test.c)
include <stdio.h>include <sys/select.h>34;hello world&34;/dev/hello&34;%d\r\n&34;open file error\r\n&34;open successe\r\n&34;%d %d\r\n&34;%s\r\n& mknod /dev/hello c 232 0
備註:這裡的232和0要跟驅動文件裡定義的主次設備號對應起來!
然後再次執行測試程序,發現成功了:
root@ubuntu:/home/jinxin/drivers/helloDev
然後再次執行dmesg查看驅動輸出,發現驅動裡的hell_open, hello_write, hello_read被依次調用了。
這就是一個完整的、最簡單的驅動的開發和測試的流程。
我想大家可能會有幾個問題:
1.驅動測試的時候為什麼要有設備文件,設備文件的作用是什麼?hello驅動的設備文件創建的時候為什麼要指定主設備號為232, 此設備號為0?
2.對/dev/hello執行write()調用的時候,怎麼就調用到了驅動裡的hello_write()裡去了?
3.測試程序的read和write的返回值為什麼都是0?
針對以上可能的問題,敬請期待《linux內核驅動第2講》,我會一一回答以上問題。
關注「技術簡說」,一步一步教你開發linux內核和驅動。