Linux 字元裝置驅動模型

2022-09-02 19:51:10 字數 3684 閱讀 6524

一。使用字元裝置驅動程式

1. 編譯/安裝驅動

在linux系統中,驅動程式通常採用核心模組的程式結構來進行編碼。因此,編譯/安裝乙個驅動程式,其實質就是編譯/安裝乙個核心模組

2. 建立裝置檔案

通過字元裝置檔案,應用程式可以使用相應的字元裝置驅動程式來控制字元裝置。

建立字元裝置檔案的方法一般有兩種:

1.使用mknod命令mknod/dev/檔名c 主裝置號  次裝置號

查詢裝置號的命令  cat /proc/devices

2. 使用函式在驅動程式中建立(後續課程介紹)

編寫應用程式時,使用命令 arm-linux-readelf  -d write_mem

3. 訪問裝置

編寫應用程式訪問裝置。

編寫了write_mem.c 和read_mem.c 訪問檔案為  /dev/memdev0  驅動為memdev

write_mem.c

#include #include 

#include

#include

intmain()

read_mem.c

int

main()

二。 字元裝置驅動模型

1. 裝置描述結構 cdev

在任何一種驅動模型中,裝置都會用核心中的一種結構來描述。

我們的字元裝置在核心中使用struct  cdev來描述。

struct  cdev

structkobjectkobj;

structmodule *owner;

const structfile_operations*ops;   //裝置操作集

structlist_headlist;

dev_tdev;  //裝置號

unsigned intcount; //裝置數

(1).字元裝置檔案與字元驅動程式如何建立起對應關係??

答案:主裝置號

驅動程式什麼來區分串列埠1和串2

答案:次裝置號

(2).linux核心中使用dev_t型別來定義裝置號,dev_t這種型別其實質為32位的unsigned int,

其中高12位為主裝置號,低20位為次裝置號.

問1:如果知道主裝置號,次裝置號,怎麼組合成dev_t型別

答:dev_t dev = mkdev(主裝置號,次裝置號)

問2: 如何從dev_t中分解出主裝置號?

答: 主裝置號= major(dev_t dev)

問3: 如何從dev_t中分解出次裝置號?

答: 次裝置號=minor(dev_t dev)

(3).如何為裝置分配乙個主裝置號?

#靜態申請開發者自己選擇乙個數字作為主裝置號,然後通過函式register_chrdev_region向核心申請使用。

缺點:如果申請使用的裝置號已經被核心中的其他驅動使用了,則申請失敗。使用的裝置號已經被核心中的其他驅動使用了,則申請失敗。

#動態分配使用alloc_chrdev_region由核心分配乙個可用的主裝置號。優點:因為核心知道哪些號已經被使用了,所以不會導致分配到已經被使用的號。

(4).不論使用何種方法分配裝置號,都應該在驅動退出時,使用unregister_chrdev_region函式釋放這些裝置號

(5). struct file_operations是乙個函式指標的集合,定義能在裝置上進行的操作。

結構中的函式指標指向驅動中的函式, 這些函式實現乙個針對裝置的操作, 對於不支援的操作則設定函式指標為null。

例如:struct file_operations dev_fops =

.llseek= null,

.read= dev_read,

.write= dev_write,

.ioctl= dev_ioctl,

.open= dev_open,

.release= dev_release,

2. 字元裝置驅動模型

1. 驅動初始化

2.1.1 分配裝置描述結構

cdev變數的定義可以採用靜態和動態兩種辦法

•靜態分配struct cdev mdev;

•動態分配struct cdev *pdev = cdev_alloc();

2.1.2 初始化裝置描述結構

struct cdev的初始化使用cdev_init函式來完成。

cdev_init(struct cdev *cdev, const struct file_operations *fops)  

引數:cdev: 待初始化的cdev結構

fops: 裝置對應的操作函式集

2.1.3 註冊裝置描述結構

字元裝置的註冊使用cdev_add函式來完成。

cdev_add(struct cdev *p, dev_t dev, unsigned count)

引數:p: 待新增到核心的字元裝置結構

dev: 裝置號

count: 該類裝置的裝置個數

2.1.4 硬體初始化

2. 實現裝置操作

1. open

int (*open) (struct inode *, struct file *)開啟裝置,響應open系統

open裝置方法是驅動程式用來為以後的操作完成初始化準備工作的。

在大部分驅動程式中,open完成如下工作:

#標明次裝置號

#啟動裝置

2. read

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *)從裝置讀取資料,響應read系統呼叫

read裝置方法通常完成2件事情:

#從裝置中讀取資料(屬於硬體訪問類操作)

#將讀取到的資料返回給應用程式

ssize_t (*read) (struct file *filp, char __user *buff, size_t count, loff_t *offp)

引數分析:filp:與字元裝置檔案關聯的file結構指標, 由核心建立.

buff : 從裝置讀取到的資料,需要儲存到的位置。由read系統呼叫提供該引數。

count: 請求傳輸的資料量,由read系統呼叫提供該引數。

offp: 檔案的讀寫位置,由核心從file結構中取出後,傳遞進來。

3. write

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)向裝置寫入資料,響應write系統呼叫

write裝置方法通常完成2件事情:

#從應用程式提供的位址中取出資料

#將資料寫入裝置(屬於硬體訪問類操作)

4. lseek

loff_t (*llseek) (struct file *, loff_t, int)重定位讀寫指標,響應lseek系統呼叫

5. close 

int (*release) (struct inode *, struct file *);關閉裝置,響應close系統呼叫

release方法的作用正好與open相反。

這個裝置方法有時也稱為close,它應該:

#關閉裝置

3. 驅動登出

當我們從核心中解除安裝驅動程式的時候,需要使用cdev_del函式來完成字元裝置的登出。

3. 範例驅動分析

字元裝置驅動模型

字元裝置是指在i o傳輸過程中以字元為單位進行傳輸的裝置,例如鍵盤,印表機等。cdev結構體 描述乙個字元裝置 struct cdev linux核心提供的一組函式用於操作cdev結構體 void cdev init 初始化cdev成員,建立cdev與file operations的連線 struc...

字元裝置驅動模型

1.裝置描述結構cdev 驅動模型種類繁多,這就需要我從眾多的模型中提取出他們的一些共性 a.驅動初始化 a.1 分配裝置描述結構 a.2 初始化裝置描述結構 a.3 註冊裝置描述結構 a.4 硬體初始化 b.實現裝置操作 c.驅動登出 裝置描述結構 在任何一種驅動模型中,裝置都會用的核心中的一種結...

Linux字元裝置驅動 經典標準字元模型

經典標準字元模型,即為linux2.6之前的早期經典標準字元模型。沒有使用乙個核心的結構體,把需要的資訊進行封裝 安裝驅動後,不會在 dev 目錄下建立裝置節點,需要使用mknod建立。乙個主裝置號只能被註冊一次,一次註冊0 255的次裝置號就被占用了。雜項裝置,每次註冊,只占用了乙個次裝置號,主裝...