1. 程式人生 > >驅動開發-1 模組hello world

驅動開發-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的內容。