應用程序使用驅動:
一個設備驅動其實就是一個內核模塊。
應用程序使用一個字符設備是通過使用其設備文件來完成的,通過對其設備文件的讀寫來完成對設備的交互:
那麼,想要使用字符設備驅動就首先得有一個字符設備文件,創建一個字符設備文件的方式有兩種:
驅動初始化
因爲驅動程序是一個內核模塊,所以驅動的初始化操作是放在內核模塊的初始化函數裏:
主要流程如下:
下面展示一段示例代碼:
下面來解釋一下這段初始化代碼中的函數和數據結構:
Struct cdev是用來表示設備的結構體,具體實現如下:
其中比較重要的就是其中特殊顏色的幾個屬性,設備操作集是指一些操作函數。設備號是用來標示設備的。設備數是用來表示同類型的設備一共有幾個,這幾個設備的主設備號相同,次設備號不同。比如串口1,串口2,它們的主設備號相同,次設備號不同。
Cdev有兩種分配方式:
Det_t類型,指的是設備號。實際爲32位的無符號整型。這個32位無符號整型包含了兩部分,分別是主設備號,和次設備號,它們相互轉化的方式爲:
分配一個設備號的方式有兩種:
因爲設備號是一種資源,所以當驅動退出的時候,應該使用unregister_chrdev_region函數釋放掉這個設備號。
Struct file_operations是一個函數指針的集合,定義的是能在設備上進行的操作,這個結構體裏就是各種函數指針,你需要重新給這些函數指針賦值,來重定向各種文件操作。下面是給這個結構體賦值的語句。
關於上面那種賦值方式只說明兩點:1.無所謂順序。2.注意下面:
Cedv_init函數使用來初始化cdev結構體的,主要是爲了將操作函數集加入到cdev中。
Cdev_add用來向內核註冊一個設備:
實現設備操作:
一般來說:常用的設備操作有以下幾個:
v int (*open) (struct inode *, struct file *)打開設備,響應open系統
Open設備方法是驅動程序用來爲以後的操作完成初始化準備工作的,在絕大部分驅動程序中,open完成如下工作:
1. 標明設備號。
2. 啓動設備
解釋一下其中的比較重要的結構體:
Struct file,在linux系統中,每一個打開的文件關聯一個struct file結構,在內核打開文件的時候創建,在文件關閉後釋放。他的重要成員如下:
Struct inode,在linux中,每一個存在於文件系統裏的文件都會關聯一個inode結構(不論有沒有打開),該結構主要記錄物理信息,主要數據結構如下:
例子程序如下:
v int (*release) (struct inode *, struct file *);關閉設備,響應close系統調用
Release方法要做的就是關閉設備。
下面是示例代碼:
v loff_t (*llseek) (struct file *, loff_t, int)重定位讀寫指針,響應lseek系統調用
文件當前讀寫指針重定位:
示例代碼:
v ssize_t (*read) (struct file *, char __user *, size_t, loff_t *)從設備讀取數據,響應read系統調用
參數意義如下:
Read設備方法通常完成兩件事情:
1. 從設備中讀取數據(屬於硬件訪問類操作)。
2. 將讀取到的數據返回給應用程序。
示例代碼:
用一張圖說明read函數的工作流程:
v ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)向設備寫入數據,響應write系統調用
Write設備方法通常完成兩件事:
1. 從應用程序提供的地址中取出數據,
2. 將數據寫入設備(屬於硬件訪問類操作)。
驅動註銷:
從內核中卸載驅動程序的時候,需要使用cdev_del函數來完成字符設備的註銷。
示例代碼: