我的第乙個驅動程式

2021-10-06 06:50:09 字數 2685 閱讀 2942

說明:

開發環境:ubuntu14.04

硬體:easyarm-i.mx283.a

linux核心屬於單核心,簡單來說,就是把很多東西都整合進核心,除了最基本的程序、執行緒管理、記憶體管理外,檔案系統,驅動,網路協議等等都在核心裡面,形成單一的核心映像,其優點在於執行效率高,核心中各模組之間的互動通過直接函式呼叫來實現。這也是和微核心最大的區別,windows採用的核心架構是微核心,微核心只實現關鍵和最核心的一部分,其餘模組被單獨編譯,模組之間的互動需要通過微核心提供的通訊機制來建立。這種通訊機制稱為訊息傳遞,微核心相當於乙個資訊交換中心。而單核心相當於乙個**集權控制中心。

微核心中只有最基本的排程、記憶體管理。驅動、檔案系統等都是使用者態的守護程序去實現的。其優點是穩定性高,驅動等的錯誤只會導致相應程序死掉,不會導致整個系統都崩潰,做驅動開發時,發現錯誤,只需要kill掉程序,修正後重啟程序就行了,比較方便。缺點是執行效率低。

相比於微核心,單核心雖然具有較高的執行效率,但是其穩定低,維護難度高。在進行驅動開發時,乙個小小的bug會倒是整個系統死掉。當開發人員重新修復bug後,必須重新編譯核心和重新啟動系統,時間消耗巨大。為了彌補這一缺點,linux引進了核心模組的概念,核心模組就是單個編譯的一段驅動**,在需要的時候可以動態載入到核心,增加核心的功能,在不需要的時候動態地解除安裝模組,而不需要重新編譯整個系統,增加了系統的可剪裁性。根據這一特點可定製屬於自己的作業系統,在一定程度上減小了核心的體積,自然節約了記憶體空間。

#include

#include

#include

static

int __init vser_init

(void

)static

void __exit vser_exit

(void

)module_init

(vser_init)

;module_exit

(vser_exit)

;module_license

("gpl");

module_author

("yangzhengqing<[email protected]>");

module_description

("a test module"

);

linux下編寫驅動程式,至少需要包含include、include、include這三個基本的檔案,這個三個檔案位於核心目錄樹下的頂層目錄include下,所以編譯驅動程式時,必須指定核心原始碼路徑。

大致了解了驅動模組的格式後,很奇怪,驅動檔案的最後為什麼增加一些必要的說明函式呢?如果不加將會出現以下的一些的警告資訊:

通過查閱資料後,其警告的大致意思是載入的驅動模組使核心被汙染了,禁止了鎖的除錯功能。原因是,linux是乙個開源的專案,為了使linux在發展的過程中不成為乙個閉源的專案,這就要求任何使用linux核心原始碼的個人或組織在免費獲得原始碼並針對原始碼做任意的修改和在發布的同時,必須將修改後的原始碼發布。這就是所謂的gpl許可證協議,所以在模組檔案的最後需要註明,表示接受這個協議。也可以不標註,但是會被限制使用一些核心的api函式。

init_module和cleanup_module模組初始化函式和清除函式的名字是固定的,為了更好地表達函式的功能意圖,開發人員可以借助核心提供的函式別名機制靈活地定義初始化函式和清除函式。

module_init和module_exit,分別用於指定init_module和cleanup_module的別名vser_init和vser_exit,如果不適用別名機制,初始化函式和清除函式的名只能是init_module和cleanup_module。另外c語言沒有命名空間的概念,使用別名機制可能會導致名字和核心中其他的函式名重複定義,為了避免這種風險,使用static修飾,限制其作用域。

linux對記憶體的使用可謂是相當勤儉持家了,任何無意義被占用的記憶體都將被**。比如,在以上模組中初始化函式在整個生命週期中,僅僅只會被呼叫一次,以後不會再被呼叫,所以呼叫結束之後應該釋放掉此記憶體,為了實現這個功能,應該使用巨集_init來達到目的。_init是把標記的函式放到可執行檔案的特定**段,再載入這些段時將會單獨分配記憶體,這些函式呼叫成功後,模組的引導程式會釋放這部分記憶體空間。_exit用於修飾清除函式,用於模組的解除安裝,如果模組不允許解除安裝,那麼這段**完全不用載入。

在以下指令碼檔案中以注釋的形式對makefile進行解釋。

#中間目標檔案

obj-m:=test.o

#當前工作目錄,驅動模組的安裝路徑,從核心原始碼路徑退回的目錄

pwd:=

$(shell pwd

)#核心原始碼的路徑

kernel_path:=/home/yzq/easyarm-imx28xx/kernel/linux-2.6.35.3

#將其賦值給另乙個環境變數

kdir:=

$(kernel_path)

#總目標

all:

$(make)

-c $(kdir)

m=$(pwd)

#清理中間檔案

.phony:clean

clean:

rm -rf *.ko *.order *.symvers *.cmd *.o *.mod.c *.tmp_versions .*.cmd .tmp_versions

我的第乙個驅動程式

arm編譯器版本 3.32 核心版本 2.6.28.7 arm號 s3c2440 驅動原始碼 include include include include include include include include define device name leds define led majo...

第乙個驅動程式

原始出處 驅動程式的開發,向來是令人感到有所畏懼的,可能很多人像我一樣,看了很久卻還是一頭霧水,不得其門而入。我們今天就通過乙個簡單的程式來使讀者學會初步的驅動程式開發。在開發windows驅動程式之前,我們需要首先安裝ddk,win98及其以前的vxd我們就不要再考慮了 windows 2000 ...

第乙個驅動程式

從今天開始就要進入核心驅動程式部分了,在這一節裡就通過第乙個驅動程式來介紹一下核心驅動模組的編寫框架。static intfirst drv open struct inode inode,struct file file static ssize t first drv write struct ...