linux字元裝置驅動

2021-07-26 09:31:01 字數 4713 閱讀 4781

linux系統裝置的3種型別:字元裝置驅動、塊裝置驅動和網路裝置驅動

字元裝置:只能乙個乙個位元組讀寫資料的裝置,不能隨機讀取裝置記憶體中的某一資料

塊裝置:可以從裝置的任意位置讀取一定長度資料的裝置

在 /dev 目錄中 執行 ls-l 時

第乙個字母為c表示該裝置為字元裝置,為b表示塊裝置

乙個字元裝置或者塊裝置都有乙個主裝置號和乙個此裝置號,統稱為裝置號。主裝置號用來表示乙個特定的驅動程式,此裝置號用來表示使用該驅動程式的各裝置。

1.主裝置號和次裝置號的表示

linux核心中 dev_t型別用來表示裝置號,在linux 2.6.34.14中

typedef u_long dev_t

u_long 在32位機中是4個位元組,64位機中是8位元組,32位中,高12位為主裝置號,低20位為次裝置號。

2.主裝置號和次裝置號的獲取

為了保障可移植性,應該使用巨集major和minor獲取主裝置號和次裝置號,mkdev巨集生成裝置號,巨集的定義如下:

#define minorbits 20                 //次裝置號的位數

#define minormask ((1u << minorbits)-1) //次裝置號掩碼 有minorbits個1

#define major(dev) ((unsigned int) ((dev) >> minorbits))

//dev右移20位得到主裝置號

#define minor(dev) ((unsigned int) ((dev) &minormask))

//與次裝置號掩碼相與得到次裝置號

#define mkdev(ma,mi) (((ma)<

3.分配裝置號

驅動開發者靜態指定乙個裝置號,核心開發者已經為常用裝置分配了裝置號,在核心原始碼/documentation/devices.txt 中可找到,此方法很可能造成裝置號衝突

建議使用方法,動態分配裝置號函式為 alloc_chrdev_region()

int register_chrdev_region(dev_t form,unsigned count,const char *name);

form :要分配的裝置號範圍的起始值,一般只提供form的主裝置號,次裝置號通常設定為0

count:需要申請的連續裝置號的個數

name:和該範圍編號關聯的裝置名稱,不能超過64位元組

成功返回0

int alloc_chr_dev_region(dev_t *dev,unsigned baseminor,unsigned count,const char *name);

dev : 輸出引數,函式成功後儲存分配到的裝置號或者連續裝置號的第乙個

baseminor : 要申請的第乙個次裝置號 通常設為0

count : 要申請的連續裝置號個數 與register_chrdev_region()函式引數相同

name : 裝置名字 與register_chrdev_region()函式引數相同

void unregister_chardev_region(dev_t form ,unsigned count);

form:要釋放的裝置號

count:從form開始要釋放的裝置號個數

4.檢視裝置號

當靜態分配裝置號時,需要檢視檔案系統中已經存在的裝置號,從而決定使用哪個裝置號,方法為讀取/proc/devices檔案,如下所示

can@ubuntu:~/c/hehe$ cat /proc/devices

character devices:

1 mem

4 /dev/vc/0

4 tty

4 ttys

5 /dev/tty

5 /dev/console

5 /dev/ptmx

5 ttyprintk

6 lp

7 vcs

10 misc

13 input

14 sound/midi

14 sound/dmmidi

21 sg

29 fb

block devices:

1 ramdisk

259 blkext

7 loop

8 sd

9 md

11 sr

65 sd

66 sd

67 sd

68 sd

69 sd

當申請字元裝置的裝置號之後,需要將字元裝置註冊到系統中,才能使用字元裝置。

linux核心中使用cdev結構體描述字元裝置,其包含了大量字元裝置所共有的特性。cdev結構體定義:

struct cdev
list 結構是乙個雙向鍊錶,用於將其他結構體連線成乙個雙向鍊錶。該結構在linux核心中廣泛使用

struct list_head
cdev結構體的list成員連線到了inode結構體i_devices成員。其中i_devices也是乙個list_head結構。cdev結構與inode結點組成了乙個雙向鍊錶。

每乙個字元裝置在/dev目錄下都有乙個裝置檔案,開啟裝置檔案就相當於開啟相應字元裝置。例如應用程式開啟裝置檔案a,那麼系統會產生乙個inode結點,通過inode結點的i_cdev欄位找到cdev結構體,通過cdev的ops指標,就能找到裝置的操作函式。

在 linux/fs.h 中定義,對裝置進行操作的抽象結構體,常用的函式有open(),read(),write(),close(),ioctl()等

某個版本linux核心中的file_operation結構體定義

struct file_operations ;
重要成員:

owner:不是乙個函式,是乙個指向這個結構模組的指標,用來維持引用計數,當模組還在使用時,不能使用rmmod解除安裝模組,幾乎所有時刻被簡單初始化為 this_module 乙個在linux/module.h中的巨集定義

llseek():改變檔案中的當前讀寫位置,將新的位置返回 loff_t型別為 long long型別

read() : 從裝置獲取資料,成功返回讀取位元組數,失敗返回負的錯誤編碼

write() : 用來邪道裝置中,成功返回寫入位元組數,失敗返回負錯誤碼

ioctl() : 執行裝置特定命令的方法

open() : 開啟乙個裝置,如果被複製為null,那麼裝置永遠開啟成功,並不會對裝置產生影響

release(): 釋放被open()函式中申請的資源,將在檔案引用計數為0時被系統呼叫,對應應用程式的close()方法,但僅當對裝置檔案的所有開啟都被釋放後才會被呼叫

常見的裝置結構體、載入函式和解除安裝函式如下:

struct ***_dev;

static

int __init ***_init(void)

//初始化cdev結構,傳遞file_operation結構指標

cdev_init(&***_dev.cdev,&***_fops);

dev->cdev.owner = this_module; //指定所屬模組

err = cdev_add(&***_dev.cdev,***_devno,1); //註冊裝置

}static

void __exit ***_exit(void)

大多數字元裝置驅動都會實現read(),write()和ioctl()函式,常見寫法如下**所示

//檔案操作結構體

static const struct file_operations ***_fops=

//讀函式

static ssize_t ***_read(struct file *filp,char _user *buf, size_t size,loff_t *ppos)

//寫函式

static ssize_t ***_write(struct file *filp,const char _user *buf,size_t size,loff_t *oppos)

//ioctl 裝置控制函式

static long ***_ioctl(struct file *file,unsigned int cmd,unsigned long arg)

return

0;}

unsigned

long copy_to_user(void _user *to,const

void *from,unsigned

long n);

unsigned

long copy_from_user(void *to,const _user *from,unsigned

long n);

put_user(local,user);

get_user(local,user);

驅動 linux裝置驅動 字元裝置驅動開發

preface 前面對linux裝置驅動的相應知識點進行了總結,現在進入實踐階段!linux 裝置驅動入門篇 linux 裝置驅動掃盲篇 fedora下的字元裝置驅動開發 開發乙個基本的字元裝置驅動 在linux核心驅動中,字元裝置是最基本的裝置驅動。字元裝置包括了裝置最基本的操作,如開啟裝置 關閉...

Linux裝置驅動之《字元裝置驅動》

linux裝置中最大的特點就是裝置操作猶如檔案操作一般,在應用層看來,硬體裝置只是乙個裝置檔案。應用程式可以像操作檔案一樣對硬體裝置進行操作,如open close read write 等。下面是乙個字元裝置驅動程式的簡單實現test.c 模組分析 1.初始化裝置驅動的結構體 struct fil...

Linux裝置驅動之字元裝置驅動

一 linux裝置的分類 linux系統將裝置分成三種基本型別,每個模組通常實現為其中某一類 字元模組 塊模組或網路模組。這三種型別有 字元裝置 字元裝置是個能夠像位元組流 類似檔案 一樣被訪問的裝置,由字元裝置驅動程式來實現這種特性。字元裝置可以通過檔案系統節點來訪問,比如 dev tty1等。這...