驅動開發-1 模組hello world
本文介紹在核心編譯模組、載入和解除安裝模組的過程。
首先開發環境是Linux-4.4.0+兩份程式碼,hello.c+Makefile。
這兩份程式碼放到哪裡呢?答案是哪裡都可以,不過要注意放在一個資料夾下。這個資料夾的位置就是Makefile中的CURRENT_PATH,編譯終端在這個資料夾開啟就行。
hello.c
/*編寫一個helloworld向核心輸出*/ #include<linux/init.h>/*包含__init和__exit*/ #include<linux/module.h>/*必須包含*/ MODULE_LICENSE("Dual BSD/GPL");/*許可證,不然載入時會提示該模組汙染核心*/ static char *name = "yr"; static int __init name_init(void) { printk("hello world!\n"); printk("hello %s!\n", name); return 0; } static void __exit name_exit(void) { printk(KERN_INFO"NAME MODULE EXIT\n"); } module_init(name_init);/*載入模組時呼叫初始化函式*/ module_exit(name_exit);/*解除安裝模組時*/ module_param(name, charp, S_IRUGO);
關鍵部分有註釋,不過這離中文註釋要當心,博主一開始用的//被報錯了。
Makefie如下:
#編譯後模組名 obj-m:=hello.o #獲取當前終端路徑 CURRENT_PATH:=$(shell pwd) #獲取Linux核心路徑名 LINUX_KERNEL_PATH:=/usr/src/linux-source-4.4.0 all: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules #C 表示進入核心目錄讀取Makefile; M 表示回到當前目錄讀Makefile clean: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
注意到makefile中的註釋是#,$(shell + commond)就是命令列執行commond的效果。大家都清楚核心版本號用uname -r得到,核心原始碼路徑LINUX_KERNEL_PATH怎麼辦呢?C檔案中的可是引用核心中的標頭檔案的。核心原始碼一般在/usr/src資料夾下,不幸的博主這個資料夾下有好多4.4.0開頭的檔案,這個方法不奏效。解決方法是在/lib/module/$(shell uname -r)/build,這裡妥妥指的就是核心版本號啦。簡單說是,如果你不清楚核心程式碼路徑,Makefile中的LINUX_KERNEL_PATH:=/lib/module/$(shell uname -r)/build。
在這兩個文件所在檔案下開終端,執行sudo make編譯,成功的話,檔案下會產生很多新檔案,比如這樣:
然而這只是最後的結果,編譯過程並沒有看上去順利。小提醒,一個大家可能會遇到的問題:***missing separator . Stop,一般是Makefile檔案中兩個make那一行開始需要用tab然而你用的是空格。如果用了tab還是會報同樣的錯——那你大概和博主遇到的問題一樣。看看gredit的編輯->首選項->編輯器,把“使用空格代替tab”前面的選項去掉。
現在已經編譯好啦~ sudo insmod ./hello.ko 載入模組,可以使用lsmod看到你的模組,dmesg看到printk的內容。
sudo rmmod hello解除安裝模組,lsmod看不到你的hello啦,dmesg可以看到對應printk的內容。