linux系統中,裝置驅動程式是作業系統核心的重要組成部分,在與硬體裝置之間建立了標準的抽象介面。通過 這個介面,使用者可以像處理普通檔案一樣,對硬體裝置進行開啟(open)、關閉(close)、讀寫(read/write)等操作。通過分析和設計裝置 驅動程式,可以深入理解linux系統和進行系統開發。本文通過乙個簡單的例子來說明裝置驅動程式的設計。
1、程式清單
#ifndef __kernel__
# define __kernel__ //按核心模組編譯
#endif
#ifndef module
# define module //裝置驅動程式模組編譯
#endif
#define device_name "mydev"
#define openspk 1
#define closespk 2
//必要的標頭檔案
#include
//同kernel.h,最基本的核心模組標頭檔案
#include
//同module.h,最基本的核心模組標頭檔案
#include
//這裡包含了進行正確性檢查的巨集
#include
//檔案系統所必需的標頭檔案
#include
//這裡包含了核心空間與使用者空間進行資料交換時的
函式巨集
#include
//i/o訪問
int my_major=0; //主裝置號
static int device_open=0;
static char message="this is from device driver";
char *message_ptr;
int my_open(struct inode *inode, struct file *file)
static void my_release(struct inode *inode, struct file *file)
ssize_t my_read (struct file *f,char *buf,int size,loff_t off)
return bytes_read;
}
ssize_t my_write (struct file *f,const char *buf, int size,loff_t off)
int my_ioctl(struct inode *inod,struct file *f,unsigned int arg1,
unsigned int arg2)
}
struct file_operations my_fops = ;
int init_module(void)
void cleanup_module(void)
2、裝置驅動程式設計
linux裝置分為字元裝置、塊裝置和網路裝置。字元裝置是不需要緩衝而直接
讀寫的裝置,如串列埠、鍵盤、滑鼠等,本例就是字元裝置驅動程式;塊裝置的訪問
通常需要緩衝來支援,以資料塊為單位來讀寫,如磁碟裝置等;網路裝置是通過套
接字來訪問的特殊裝置。
1) 裝置驅動程式和核心與應用程式的介面
無論哪種型別的裝置,linux都是通過在核心中維護特殊的裝置控制塊來與設
備驅動程式介面的。在字元裝置和塊裝置的控制塊中,有乙個重要的資料結構
file_operations,該結構中包含了驅動程式提供給應用程式訪問硬體裝置的各種
方法,其定義如下(參見fs.h):
struct file_operations ;
多數情況下,只需為上面結構中的少數方法編寫服務函式,其他均設為null即可。
每乙個可裝配的裝置驅動程式都必須有init_module和cleanup_module兩個函式,裝載和解除安裝裝置時核心自動呼叫這兩個函式。在 init_module中,除了可以對硬體裝置進行檢查和初始化外,還必須呼叫register_* 函式將裝置登記到系統中。本例中是通過register_chrdev來登記的,如果是塊裝置或網路裝置則應該用
register_blkdev和register_netdev來登記。register_chrdev 的主要功能是將設
備名和結構file_operations登記到系統的裝置控制塊中。
2) 與應用程式的資料交換
由於裝置驅動程式工作在核心儲存空間,不能簡單地用"="、"memcpy"等方法與應用程式交換資料。在標頭檔案uaccess.h中定義了方法put_user(x, ptr)和
get_user(x, ptr),用於核心空間與使用者空間的資料交換。值x的型別根據指標
ptr的型別確定,請參見源**中的my_read與my_write函式。
3) 與硬體裝置的介面
linux中為裝置驅動程式訪問i/o埠、硬體中斷和dma提供了簡便方法,相應的標頭檔案分別為io.h、irq.h、dma.h。由於篇輻限制,本例 中只涉及到i/o埠訪問。linux提供的i/o埠訪問方法主要有:inb()、inw()、outb()、outw()、inb_p()、 inw_p()、outb_p()、outw_p()等。要注意的是,裝置驅動程式在使用埠前,應該先用check_region()檢查該埠的占用 情況,如果指定的埠可用,則再用request_region()向系統登記。說明check_region()、request_region()的 標頭檔案是ioport.h。
4) 記憶體分配
裝置驅動程式作為核心的一部分,不能使用虛擬記憶體,必須利用核心提供的
kmalloc()與kfree()來申請和釋放核心儲存空間。kmalloc()帶兩個引數,第乙個
要申請的是記憶體數量,在早期的版本中,這個數量必須是2的整數冪,如128、256
。關於kmalloc()與kfree()的用法,可參考核心源程式中的malloc.h與slab.c程式
。
3、程式的編譯和訪問
本例在linux 2.2.x.x中可以成功編譯和執行。先用下面的命令列進行編譯:
gcc -wall -o2 -c mydev.c該命令列中引數-wall告訴編譯程式顯示警告資訊;引數-o2是關於**優化的設定,注意核心模組必須優化;引數-c規定只進行編譯和匯 編,不進行連線。正確編譯後,形成mydev.o檔案。可以輸入命insmod mydev.o來裝載此程式。如果裝配成功,則顯示資訊:register ok.major-number=xx。利用命令lsmod可以看到該模組被裝配到系統中。為了訪問該模組,應該用命令mknode來建立裝置檔案。下面 的應用程式可以對建立的裝置檔案進行訪問。
#include
#include
#include
#define device_name mydev
#define openspk 1
#define closespk 2
char buf[128];
int main()
Linux裝置驅動程式設計例項
linux系統中,裝置驅動程式是作業系統核心的重要組成部分,在 與硬體裝置之間 建立了標準的抽象介面。通過這個介面,使用者可以像處理普通檔案一樣,對硬體設 備進行開啟 open 關閉 close 讀寫 read write 等操作。通過分析和設計設 備驅動程式,可以深入理解linux系統和進行系統開...
Linux裝置驅動程式設計例項
linux系統中,裝置驅動程式是作業系統核心的重要組成部分,在 與硬體裝置之間建立了標準的抽象介面。通過這個介面,使用者可以像處理普通檔案一樣,對硬體裝置進行開啟 open 關閉 close 讀寫 read write 等操作。通過分析和設計裝置驅動程式,可以深入理解linux系統和進行系統開發。本...
裝置驅動例項 字元裝置驅動
在整個linux裝置驅動學習中,字元裝置驅動較為基礎。通過對它的學習,對裝置驅動進一步加深了解 cdev 結構體struct cdev 講下比較重要的成員變數 dev t dev 定義了32位的裝置號,其中12位是主裝置號,20位是從裝置號。獲取主裝置號 major dev t dev 獲取從裝置號...