技術(shù)員聯(lián)盟提供win764位系統(tǒng)下載,win10,win7,xp,裝機純凈版,64位旗艦版,綠色軟件,免費軟件下載基地!

當(dāng)前位置:主頁 > 教程 > 電腦常識 >

linux驅(qū)動程序開發(fā)詳細(xì)介紹

來源:技術(shù)員聯(lián)盟┆發(fā)布時間:2018-08-21 06:10┆點擊:

第一個內(nèi)核模塊(Hello World模塊)
代碼如下:
View Code
#include<linux/init.h>
#include<linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static __init int hello_init(void)
{
//printk函數(shù)在內(nèi)核中定義對模塊可用,內(nèi)核需要自已的打印涵數(shù)
//因為它靠自已運行,而沒有相應(yīng)的庫函數(shù)。
//模塊能夠調(diào)用printk是因為insmod加載了之后,模塊被鏈接到內(nèi)核
//因些可調(diào)用內(nèi)核的公用符號,KERN_ALERT是消息的優(yōu)先級
printk(KERN_ALERT"HELLO WORLDn");
return 0;
}
static __exit void hello_exit(void)
{
printk(KERN_ALERT"GoodByen");
}
module_init(hello_init);
module_exit(hello_exit);

在這個模塊中定義了兩個函數(shù),一個在模塊加載到內(nèi)核時調(diào)用(hello_init),另一個在從內(nèi)核將模塊移出時調(diào)用(hello_exit);在上面的代碼中,module_init與module_exit是兩個內(nèi)核宏定義,用于告訴內(nèi)核從哪里啟動,從哪里退出,MODULE_LICENSE宏用于聲明模塊是遵守某個自由許可證的,否則內(nèi)核加載時會出現(xiàn)警告。
好了,現(xiàn)在可以對上面這個程序進行相應(yīng)的測試,在測試之前必須要編寫相應(yīng)的Makefile文件,模塊的編譯與普通程序的編譯是不同的

Makefile文件

代碼如下:
View Code
#makefile for hello world
# KERNELRELEASE是在內(nèi)核源碼中定義的第一個變量
ifneq ($(KERNELRELEASE),) #判斷變量是否為空(第一次執(zhí)行時沒有定義)
#沒定義時執(zhí)行else語句
obj-m := HelloWorld.o#表明有一個模塊要從目錄文件HelloWorld.o建立,建立之后將其
#命名為HelloWorld.ko
#如果有一個模塊名為module.ko,來自于兩個源文件,假設(shè)為file1.c與file2.c
#則應(yīng)該這樣 obj-m := module.o
# module-objs:=file1.o file2.o
else
KDIR:=http://www.3lian.com/lib/modules/$(shell uname -r)/build
all:
#當(dāng)make的目標(biāo)為all時,-C $(KDIR)跳到內(nèi)核源碼目錄下讀取Makefile
#M=$(PWD)表示返回當(dāng)前目錄繼續(xù)讀取,執(zhí)行當(dāng)前的Makefile,當(dāng)再次執(zhí)行時
#$(KERNELRELEASE)已經(jīng)定義,make將讀取else之前的內(nèi)容
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.ko *.o *.mod.o *.mod.c *.symvers
endif

相應(yīng)的解釋如上
 
開如編譯內(nèi)核:必須要是超級用戶
在當(dāng)前路徑下輸入make
編譯完成后,輸入insmd HelloWorld.ko進行內(nèi)核的加載,使用dmesg |tail可以查看內(nèi)核的輸出信息。
移除內(nèi)核采用rmmod HelloWorld 相應(yīng)的使用dmesg|tail可以看到打印出GoodBye
Printk可能沒有輸出到屏幕上,這與KERN_ALERT的優(yōu)先級有關(guān),說明還不夠高,內(nèi)核輸出的內(nèi)容實際在/var/log/kern.log中,可以vim /var/log/kern.log查看。
內(nèi)核模塊與應(yīng)用程序的不同:
1:應(yīng)用程序運行后就會處理相應(yīng)的任務(wù),而內(nèi)核模塊注冊后是用來服務(wù)于將來請求,并且初始化函數(shù)加了__init之后,調(diào)用完后,內(nèi)存空間立即釋放。
2:應(yīng)用程序終止時可以不用負(fù)責(zé)回收資源,由操作系統(tǒng)來維護,但內(nèi)核模塊在除時必須釋放資源。
3:應(yīng)用程序可以調(diào)用相應(yīng)的庫函數(shù),而內(nèi)核模塊能夠調(diào)用的則只要內(nèi)核中輸入的那些函數(shù)。在內(nèi)核模塊的編程中,源文件不應(yīng)當(dāng)包括通常的頭文件,但也有例外,如<stdarg.h>等少部分頭文件是僅有的例外。
4:錯誤的處理方式不同,在應(yīng)用程序中段錯誤,可以由相應(yīng)的調(diào)試程序進行檢查更改,但內(nèi)核模塊中,段錯誤,如果不終止整個系統(tǒng)的話,就會終止當(dāng)前進程。
用戶空間與內(nèi)核空間:
應(yīng)用程序在用戶空間運行,而內(nèi)核模塊是在內(nèi)核空間內(nèi)運行的。每種模式都有它自已的內(nèi)存映射,它自已的地址空間。
內(nèi)核與當(dāng)前進程的關(guān)系:
內(nèi)核模塊做的大部份動作是代表一個特定進程的,內(nèi)核代碼可以引用當(dāng)前進程,通過存取全局項current,它在<asm/cuurent.h>定義:
#define current get_current()//通過這個宏定義可以獲取指向task_struct的任務(wù)指針
內(nèi)核代碼可以通過current來使用進程特定的信息。

內(nèi)核符號表:

內(nèi)核模塊在加載時通過查找內(nèi)核符號表來解決未定義的符號,內(nèi)核符號表包涵了全局內(nèi)核項的地址,當(dāng)加載一個模塊時,模塊中輸出的符號也將成為內(nèi)核符號表的一部分。
模塊的輸入符號通常采用以下兩種形式:
EXPORT_SYMBOL(name)
EXPORT_SYMBOL_GPL(name)
上面的宏定義中的任何一個使得給定的符號在模塊外使用,_GPL版本的宏定義只能使符號對_GPL許可的模塊可用。
版本依賴:
模塊代碼一定要為每個它要連接的內(nèi)核版本重新編譯,在模塊編譯的過程中,其中一步是到當(dāng)前的內(nèi)核對讀取Makefile文件,在編譯的過程中會采用內(nèi)核樹中的文件(vermagic.o)連接你的模塊,在這個文件里面有許多有關(guān)內(nèi)核的信息,包括版本...
模塊參數(shù):
模塊參數(shù)由insmod與modprobe在加載時指定。
對前面的HelloWorld.c進行修改如下:
在終端上輸入


代碼如下:
Make
Insmod HelloWorld.ko who=”test” num=10
Dmesg|tail -3