Linux字元裝置驅動總結

2021-06-08 09:07:18 字數 4868 閱讀 8661

linux2.6核心中使用cdev結構體描述字元裝置:

struct

cdev

;

cdev結構體的dev_t定義了裝置號,32位。高12位為主裝置號,低20位為次裝置號。

下列巨集可從dev_t獲得主、次裝置號:

major(dev_t

dev)

minor(dev_t

dev)

通過主、次裝置號生成dev_t:

mkdev(int

major,

int

minor)

一組函式操作cdev結構體:

void

cdev_init(struct

cdev*,

struct

file_operations

*); //

初始化cdev成員,建立cdev和file_operations之間的連線

struct

cdev

*cdev_alloc(void); // 動態申請乙個cdev記憶體

void

cdev_put(struct

cdev

*p); // 減少模組的引用計數,釋放結構體空間

int

cdev_add(struct

cdev*,

dev_t,

unsigned); // 向系統新增乙個dev,完成字元裝置的註冊,常用於模組載入函式中

void

cdev_del(struct

cdev

*);// 向系統刪除乙個dev,完成字元裝置的登出,常用於模組解除安裝函式中

呼叫cdev_add()前,先呼叫register_chrdev_region()或alloc_chrdev_region():

int

register_chrdev_region(dev_t

from,

unsigned

count,

constchar

*name); // 用於已知起始裝置號

int

alloc_chrdev_region(dev_t

*dev,

unsigned

baseminor,

unsigned

count,

constchar

*name); // 裝置號未知,向系統動態申請未占用裝置號放入dev

cdev_del()後,unregister_chrdev_region()應被呼叫以釋放裝置號:

void

unregister_chrdev_region(

dev_t

from

,unsignedcount);

file_operations結構:

1

struct

file_operations

;

linux字元裝置驅動函式模板:

//

裝置結構體

struct

***_dev_t

//裝置驅動模組載入函式

staticint

__init

***_init(void)

else

ret=

cdev_add(

&***_dev

.cdev,

***_dev_no,

1);

// 註冊裝置..

.}//裝置驅動模組解除安裝函式

staticvoid

__exit

***_exit(void)

//讀裝置

//filp是檔案結構指標,buf是使用者空間的記憶體位址,該位址空間不能直接讀寫,count是要讀的位元組數,f_pos是讀的位置相對於檔案開頭的偏移

ssize_t

***_read(struct

file

*filp,

char

__user

*buf,

size_t

count,

loff_t

*fpos)

//寫裝置

ssize_t

***_write(struct

file

*filp,

constchar

__user

*buf,

size_t

count,

loff_t

*fpos)

//ioctl函式

int

***_ioctl(struct

inode

*inode,

struct

file

*filp,

unsignedint

cmd,

unsignedlong

arg)

return0;}//

字元裝置檔案操作結構體,在模組載入函式的cdev_init(&***_dev.cdev, &***_fops)的語句中被建立與cdev的連線

struct

file_operations

***_fops=;

其他說明:

核心空間和使用者空間的記憶體不能直接訪問,需借助copy_from_user()和copy_to_user():

unsignedlong

copy_from_user(void

*to,

constvoid

__user

*from,

unsignedlong

count);

unsignedlong

copy_to_user(void

__user

*to,

constvoid

*from,

unsignedlong

count);

上述函式返回不能被複製的位元組數。若完全複製成功,返回0.

若要複製的記憶體是簡單型別,如char、int、long等,則可以使用簡單的put_user()和get_user():

int

val; //

核心空間整形變數..

.get_user(val,

(int

*)arg); //

使用者空間到核心空間,arg是使用者空間的位址..

.put_user(val,

(int

*)arg);//

核心空間到使用者空間,arg是使用者空間的位址

讀和寫函式中的__user是乙個巨集,表明其後的指標指向使用者空間:

#ifdef

__checker__

#define

__user

__attribute__((noderef,

address_space(1)))

#else

#define

__user

#endif

Linux字元裝置驅動總結

linux2.6核心中使用cdev結構體描述字元裝置 struct cdev cdev結構體的dev t定義了裝置號,32位。高12位為主裝置號,低20位為次裝置號。下列巨集可從dev t獲得主 次裝置號 major dev t dev minor dev t dev 通過主 次裝置號生成dev t...

Linux字元裝置驅動框架總結

對於linux而言,一切皆檔案,在linux系統下,所有檔案都可以像文字檔案一樣open read write,那麼對於linux裝置驅動而言,比如現在有乙個點燈的驅動程式,它的裝置節點是 dev 當應用程式執行open read write的時候,是如何呼叫到驅動程式裡的open read wri...

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

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