天天看點

【Linux驅動】字元裝置驅動

一、linux系統将裝置分為3類:字元裝置、塊裝置、網絡裝置。使用驅動程式:

【Linux驅動】字元裝置驅動

1、字元裝置:是指隻能一個位元組一個位元組讀寫的裝置,不能随機讀取裝置記憶體中的某一資料,讀取資料需要按照先後資料。字元裝置是面向流的裝置,常見的字元裝置有滑鼠、鍵盤、序列槽、控制台和LED裝置等。

2、塊裝置:是指可以從裝置的任意位置讀取一定長度資料的裝置。塊裝置包括硬碟、磁盤、U盤和SD卡等。

  每一個字元裝置或塊裝置都在/dev目錄下對應一個裝置檔案。linux使用者程式通過裝置檔案(或稱裝置節點)來使用驅動程式操作字元裝置和塊裝置。

3、字元裝置驅動模型

【Linux驅動】字元裝置驅動

二、字元裝置驅動程式基礎:

1、主裝置号和次裝置号(二者一起為裝置号):

  一個字元裝置或塊裝置都有一個主裝置号和一個次裝置号。主裝置号用來辨別與裝置檔案相連的驅動程式,用來反映裝置類型。次裝置号被驅動程式用來辨識操作的是哪個裝置,用來區分同類型的裝置。

  linux核心中,裝置号用dev_t來描述,2.6.28中定義如下:

  typedef u_long dev_t;

  在32位機中是4個位元組,高12位表示主裝置号,低12位表示次裝置号。

可以使用下列宏從dev_t中獲得主次裝置号:                   也可以使用下列宏通過主次裝置号生成dev_t:

MAJOR(dev_t dev);                              MKDEV(int major,int minor);

MINOR(dev_t dev);

【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動

2、配置設定裝置号(兩種方法):

(1)靜态申請:

int register_chrdev_region(dev_t from, unsigned count, const char *name);

【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動

(2)動态配置設定:

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

【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動

登出裝置号:

void unregister_chrdev_region(dev_t from, unsigned count);

建立裝置檔案:

利用cat /proc/devices檢視申請到的裝置名,裝置号。

(1)使用mknod手工建立:mknod filename type major minor

(2)自動建立;

  利用udev(mdev)來實作裝置檔案的自動建立,首先應保證支援udev(mdev),由busybox配置。在驅動初始化代碼裡調用class_create為該裝置建立一個class,再為每個裝置調用device_create建立對應的裝置。

3、字元裝置驅動程式重要的資料結構:

(1)struct file:代表一個打開的檔案描述符,系統中每一個打開的檔案在核心中都有一個關聯的struct file。它由核心在open時建立,并傳遞給在檔案上操作的任何函數,直到最後關閉。當檔案的所有執行個體都關閉之後,核心釋放這個資料結構。

【Linux驅動】字元裝置驅動

(2)struct inode:用來記錄檔案的實體資訊。它和代表打開的file結構是不同的。一個檔案可以對應多個file結構,但隻有一個inode結構。inode一般作為file_operations結構中函數的參數傳遞過來。

  inode譯成中文就是索引節點。每個儲存設備或儲存設備的分區(儲存設備是硬碟、軟碟、U盤 ... ... )被格式化為檔案系統後,應該有兩部份,一部份是inode,另一部份是Block,Block是用來存儲資料用的。而inode呢,就是用來存儲這些資料的資訊,這些資訊包括檔案大小、屬主、歸屬的使用者組、讀寫權限等。inode為每個檔案進行資訊索引,是以就有了inode的數值。作業系統根據指令,能通過inode值最快的找到相對應的檔案。

【Linux驅動】字元裝置驅動

(3)struct file_operations

【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動

三、字元裝置驅動程式設計:

1.裝置注冊:

在linux2.6核心中,字元裝置使用struct cdev來描述;

【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動

字元裝置的注冊分為三個步驟:

(1)配置設定cdev: struct cdev *cdev_alloc(void);

(2)初始化cdev: void cdev_init(struct cdev *cdev, const struct file_operations *fops);

(3)添加cdev: int cdev_add(struct cdev *p, dev_t dev, unsigned count)

【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動

2.裝置操作的實作:file_operations函數集的實作(要明确某個函數什麼時候被調用?調用來做什麼操作?)

特别注意:驅動程式應用程式的資料交換:

  驅動程式和應用程式的資料交換是非常重要的。file_operations中的read()和write()函數,就是用來在驅動程式和應用程式間交換資料的。通過資料交換,驅動程式和應用程式可以彼此了解對方的情況。但是驅動程式和應用程式屬于不同的位址空間。驅動程式不能直接通路應用程式的位址空間;同樣應用程式也不能直接通路驅動程式的位址空間,否則會破壞彼此空間中的資料,進而造成系統崩潰,或者資料損壞。安全的方法是使用核心提供的專用函數,完成資料在應用程式空間和驅動程式空間的交換。這些函數對使用者程式傳過來的指針進行了嚴格的檢查和必要的轉換,進而保證使用者程式與驅動程式交換資料的安全性。這些函數有:

3.裝置登出:void cdev_del(struct cdev *p);

四、字元裝置驅動小結:

  字元裝置是3大類裝置(字元裝置、塊裝置、網絡裝置)中較簡單的一類裝置,其驅動程式中完成的主要工作是初始化、添加和删除cdev結構體,申請和釋放裝置号,以及填充file_operation結構體中操作函數,并實作file_operations結構體中的read()、write()、ioctl()等重要函數。如圖所示為cdev結構體、file_operations和使用者空間調用驅動的關系。

【Linux驅動】字元裝置驅動

五:字元裝置驅動程式分析:

(1)memdev.h

【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動

(2)memdev.c

【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動

(3)應用程式(測試檔案):app-mem.c

【Linux驅動】字元裝置驅動
【Linux驅動】字元裝置驅動

測試步驟:

繼續閱讀