linux核心字元裝置驅動開發

2021-10-04 13:04:45 字數 4769 閱讀 6401

1,對驅動的理解:對於一般驅動程式來說,只需要配置控制器的暫存器就可以;但是在linux作業系統中,軟體要讓硬體辦事,就要滿足硬體的規矩,也就是按驅動框架來開發硬體驅動程式;驅動程式就要受到linux的約束,這個約束就被稱為linux驅動框架。linux的驅動框架有很多:字元裝置驅動框架、塊裝置驅動框架、網路裝置驅動框架、spi匯流排驅動框架、usb匯流排驅動框架、platform匯流排驅動框架。

2,特點:同樣字元裝置在linux系統下,以字元裝置檔案形式供使用者訪問使用,使用者訪問字元裝置檔案,本質就是訪問對應的字元裝置硬體

3,字元裝置檔案存在於根檔案系統的/dev/下的裝置節點目錄,字元裝置檔案包含的檔案屬性

ls    /dev/ttyul*    -lh

crw-rw----     204,  64 /dev/ttyul1

crw-rw----     204,  65 /dev/ttyul2

crw-rw----     204,  66 /dev/ttyul3

「c」:表示此裝置為字元裝置

"204":表示裝置檔案對應的主裝置號

"64/65/66":表示裝置檔案對應的此裝置號

"ttyul1":表示第乙個串列埠的裝置檔名,  "ttyul3":表示第二個串列埠的裝置檔名,  "ttyul3":表示第三個串列埠的裝置檔名

4,字元裝置檔案建立

mknod /dev/字元裝置檔名   c 主裝置號    次裝置號

例如:mknod /dev/lisi c 250 0

5.裝置號,主裝置號,次裝置號

主裝置號功能:應用程式根據裝置檔案的主裝置號在核心茫茫的裝置驅動中找到適合自己的驅動,乙個驅動只能有唯一的主裝置號

次裝置號功能:驅動根據次裝置號來找到要訪問的硬體 如果乙個驅動管理乙個硬體,次裝置號一般給0即可。

總結:主裝置號和次裝置號對於核心來說,是一種寶貴的資源 乙個驅動要向有乙個主裝置號和次裝置號,首先應該向核心去申請資源!

裝置號就是包含了主裝置號和次裝置號!                               

裝置號對應的資料型別:dev_t  (本質是unsigned int)     

裝置號的高12位儲存的就是主裝置號

裝置號的低20位儲存的就是次裝置號

裝置號 = mkdev(主裝置號,次裝置號); //根據主,次裝置號合併乙個裝置號

主裝置號 = major(裝置號); //根據裝置號提取主裝置號

次裝置號 = minor(裝置號); //根據裝置號提取次裝置號

問:既然裝置號對於核心來說是一種寶貴的資源,驅動如何向核心去申請和釋放資源呢?

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

函式功能:向核心申請裝置號

引數:dev:儲存申請的裝置號資訊

baseminor:希望起始的次裝置號,一般給0

count:次裝置號的個數

name:裝置名稱,將來通過cat /proc/devices檢視

void unregister_chrdev_region(dev_t dev, unsigned count)

函式功能:釋放裝置號資源

引數:dev:申請的裝置號

count:次裝置號的個數

6.自行設計描述字元裝置驅動的資料結構

struct char_device

dev_t dev; //儲存申請的裝置號資訊

int count; //儲存次裝置號的個數

char *name; //字元裝置的名稱

int (*open)(void); //開啟裝置介面

int (*close)(void); //關閉裝置介面

int (*read)(void); //讀裝置介面

int (*write)(void); //寫裝置介面

優化資料結構:

//宣告描述硬體的操作方法

struct file_operations

int (*open)(void); //開啟裝置介面

int (*close)(void); //關閉裝置介面

int (*read)(void); //讀裝置介面

int (*write)(void); //寫裝置介面

//宣告描述字元裝置驅動的資料結構

struct char_device

dev_t dev; //儲存申請的裝置號資訊

int count; //儲存次裝置號的個數

char *name; //字元裝置的名稱

struct file_operations *ops; //字元裝置驅動的硬體操作介面

7.核心描述字元裝置驅動的資料結構

struct cdev

dev_t dev; //儲存申請的裝置號資訊

int count; //儲存次裝置號的個數

struct file_operations *ops; //字元裝置驅動的硬體操作介面

...  //其餘字段核心單獨使用

//核心描述硬體操作方法

struct file_operations

int (*open) (struct inode *, struct file *);

int (*release) (struct inode *, struct file *);

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

應用和底層驅動呼叫關係:

應用程式open->c庫open->軟中斷->核心的sys_open->驅動open介面

應用程式close->c庫close->軟中斷->核心的sys_close->驅動release介面

應用程式read->c庫read->軟中斷->核心的sys_read->驅動read介面

應用程式write->c庫write->軟中斷->核心的sys_write->驅動write

二,字元裝置驅動的步驟:

1,module_init(my_driver_init);//載入核心模組

2.定義初始化字元裝置驅動的硬體操作介面物件

struct file_operations led_fops =

.open = led_open, //開啟裝置

.release = led_close, //關閉裝置

.read = led_read, //讀裝置

.write = led_write //寫裝置

切記:驅動介面將來要服務使用者,要定義哪些介面 要嚴格按照使用者的需求來定

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

void unregister_chrdev_region(dev_t dev, unsigned count)

3.定義初始化字元裝置驅動物件

struct cdev led_cdev; //定義物件

cdev_init(&led_cdev, &led_fops); //初始化物件,給字元裝置物件新增硬體操作介面

4.向核心註冊新增乙個字元裝置物件:

cdev_add(&led_cdev, 申請好的裝置號, 次裝置號的個數);或major = register_chrdev(0, "my_drv", &first_drv_fops); // 註冊, 告訴核心

至此核心就有了乙個真實的字元裝置驅動,並且有了相關的操作介面

5.解除安裝字元裝置物件

module_exit(my_driver_init);//解除安裝核心模組,一旦解除安裝,核心就不存在乙個字元裝置驅動!

6,涉及標頭檔案:

#include

#include

總結:編寫字元裝置驅動步驟:實現乙個字元裝置驅動的步驟:兩個資料結構+3個配套函式

(1).先寫框架

(2).該宣告的宣告,該定義的定義;宣告和定義時,先搞硬體資訊,後搞軟體資訊;

(3).再填充入口和出口:先寫注釋後填**

(4).最後完成各個介面函式

三,字元裝置驅動框架

四,驅動**舉例

#include #include #include #include #include #include #include #include static struct class *mydrv_class;

static struct class_device *mydrv_class_dev;

static ssize_t my_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)

static struct file_operations my_drv_fops = ;

static int my_drv_init(void)

static void my_drv_exit(void)

module_init(my_drv_init);

module_exit(my_drv_exit);

module_license("gpl");

Linux裝置驅動 核心開發

linux裝置驅動需要使用核心api來實現,一般被包含在linux核心原始碼樹中。驅動可以編譯到核心,隨著核心一起在系統啟動的時候被載入。也可以編譯成核心模組,在系統執行起來之後動態地載入到核心中,使得除錯的時候無需重新編譯核心,也無需重啟系統,很大程度上方便了驅動 的除錯。但並不是只有裝置驅動才能...

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

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

Linux核心之字元裝置驅動

學習計畫 1.vfs 虛擬檔案系統 vfs的作用就是採用標準的unix系統呼叫讀寫位於不同物理介質上的不同檔案系統。vfs是乙個可 以讓open read write 等系統呼叫不用關心底層的儲存介質和檔案系統型別就可以工作的 粘合層。在古老的dos作業系統中,要訪問本地檔案系統之外的檔案系統需要使...