linux系統中,裝置驅動程式是作業系統核心的重要組成部分,在 與硬體裝置之間
建立了標準的抽象介面。通過這個介面,使用者可以像處理普通檔案一樣,對硬體設
備進行開啟(open)、關閉(close)、讀寫(read/write)等操作。通過分析和設計設
備驅動程式,可以深入理解linux系統和進行系統開發。本文通過乙個簡單的例子
來說明裝置驅動程式的設計。
1、 程式清單
// mydev.c 2023年2月7日編寫
#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檔案。可以輸入命令in**od mydev.o來裝載此程式。如
果裝配成功,則顯示資訊:register ok.major-number=xx。利用命令l**od可以看
到該模組被裝配到系統中。
為了訪問該模組,應該用命令mknode來建立裝置檔案。下面的應用程式可以對建立
的裝置檔案進行訪問。
本文**
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 獲取從裝置號...