Linux字元裝置驅動總結

2021-06-22 05:37:35 字數 3881 閱讀 3357

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

struct

cdev

;

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

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

major(dev_t

dev)

minor(dev_t

dev)

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

mkdev(

intmajor,

intminor)

一組函式操作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);  // 減少模組的引用計數,釋放結構體空間

intcdev_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,

const

char

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

intalloc_chrdev_region(dev_t

*dev,

unsigned

baseminor,

unsigned

count,

const

char

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

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

void

unregister_chrdev_region(

dev_t

from

,unsigned 

count);

file_operations結構:

struct

file_operations

;

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

//

裝置結構體

struct

***_dev_t

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

static

int__init

***_init(

void

)else

ret=

cdev_add(

&***_dev

.cdev,

***_dev_no,1);

// 註冊裝置..

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

static

void

__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,

const

char

__user

*buf,

size_t

count,

loff_t

*fpos)

//ioctl函式

int***_ioctl(

struct

inode

*inode,

struct

file

*filp,

unsigned

intcmd,

unsigned

long

arg)

return0;

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

struct

file_operations

***_fops=;

其他說明:

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

unsigned

long

copy_from_user(

void

*to,

const

void

__user

*from,

unsigned

long

count);

unsigned

long

copy_to_user(

void

__user

*to,

const

void

*from,

unsigned

long

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核心驅動中,字元裝置是最基本的裝置驅動。字元裝置包括了裝置最基本的操作,如開啟裝置 關閉...