裝置驅動例項 字元裝置驅動

2021-07-24 11:05:22 字數 2824 閱讀 6265

在整個linux裝置驅動學習中,字元裝置驅動較為基礎。通過對它的學習,對裝置驅動進一步加深了解

cdev 結構體

struct cdev;

講下比較重要的成員變數

dev_t dev 定義了32位的裝置號,其中12位是主裝置號,20位是從裝置號。

獲取主裝置號:major(dev_t dev)

獲取從裝置號:minor(dev_t dev)

通過主裝置號和從裝置號生成裝置號:mkdev(int major, int minor)

struct file_operations *ops定義了字元裝置驅動提供給虛擬檔案系統的介面函式

linux核心提供了一組函式用於操作cdev結構體

cdev_init() : 初始化cdev成員,並將函式引數中的檔案操作結構體指標file_operation

賦值給cdev中的ops

cdev_alloc() : 動態申請乙個cdev記憶體

cdev_add() :

向系統新增乙個cdev,完成字元裝置的註冊。

該函式的呼叫通常發生在字元裝置驅動模組載入函式中

在註冊字元裝置之前,首先呼叫register_chrdev_region()(用在已知起始裝置號)

alloc_chrdev_region()(用在裝置號未知,動態申請裝置號的時候)函式

向系統申請裝置號。

cdev_del() :

向系統刪除乙個cdev,完成字元裝置的登出。

該函式的呼叫通常發生在字元裝置驅動模組解除安裝函式中

在完成字元裝置的登出之後,需要呼叫unregister_chrdev_region()釋放原先申請的裝置號。

file_operations結構體
file_operation 結構體中的成員函式是字元裝置驅動程式設計的主體內容。當應用程式呼叫linux的open()\write()\read()\close()等系統呼叫的時候,最後還是通過核心呼叫的file_operation結構體裡面的函式。

file_operation的結構體如下:很大我只挑一些出來分析

llseek() : 用來修改乙個檔案的當前讀寫位置,並將新位置返回,出錯返回負值。

read(): 與使用者應用程式裡面的read和fread相對應

write(): 與使用者應用程式裡面的write和fwrite相對應

read/write返回0則暗示eof。

unlocked_ioctl()提供裝置相關控制命令的實現,與使用者應用程式裡面的fcntl和ioctl對應。

mmap()函式將裝置記憶體對映到程序的虛擬位址空間中,這個函式對於幀緩衝等裝置有特殊的意義,

幀緩衝被對映到使用者空間之後,應用程式可以直接訪問它而無須在核心和應用間進行記憶體複製

與應用程式的中的void mmap函式對應

poll()函式一般用於詢問裝置是否可被非阻塞地立即讀寫。當詢問的條件未被觸發時,使用者空間進行select和poll的系統呼叫會引起程序的阻塞

aio_read()和aio_write函式分別對與檔案描述符對應的裝置進行非同步讀寫操作。

裝置實現這兩個函式,使用者空間可以對裝置檔案描述符進行sys_io_setup/sys_io_submit/sys_io_getevents/sys_io_destroy等系統呼叫

字元裝置驅動模組載入和解除安裝函式
載入函式:實現裝置號的申請和cdev的註冊

解除安裝函式:實現裝置號的釋放和cdev的登出

//裝置結構體

struct ***_dev_t ***_dev;

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

static int __init ***_init(void)

else

//註冊裝置

ret = cdev_add(&***_dev.cdev, ***_dev_no, 1);

...}//解除安裝函式

statc void __exit ***_exit(void)

file_operations結構體中的成員函式

大多數的字元裝置驅動會實現read()/write()/ioctl()函式

ssize_t ***_read(struct file*filp, char __user *buf, 

size_t count, loff_t *f_pos)

ssize_t ***_write(struct file*filp, char __user *buf,

size_t count, loff_t *f_pos)

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

...}flip: 檔案結構體指標

buf: 使用者空間記憶體的位址

count:讀寫的位元組數

f_ops:讀寫位置相對於檔案開頭的偏移

由於使用者空間不能直接訪問核心空間的記憶體,因此借助了copy_from_user完成從使用者空間緩衝區到核心空間緩衝區的copy,同理應用於copy_to_user函式。

如果是簡單型別用get_user或者put_user也可以的

__user是乙個巨集,表明其後的指標指向使用者空間

核心空間雖然可以訪問使用者空間的緩衝區,但是需要先檢查其合法性,通過access_ok來進行判斷

i/o控制函式的cmd引數為實現定義好的i/o控制命令,而arg為對應於該命令的引數。

需要定義乙個file_operations的例項
將具體裝置驅動的函式複製給file_operation的成員

struct file_operations ***_fops = ;

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

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

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

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

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

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