標籤:blog http com 使用 檔案 資料
轉自:http://blog.sina.com.cn/s/blog_55465b470100eb8c.html
這裡貼部分內容:
Chapter 2. 裝置驅動程式開發
在編程思路上,機製表示需要提供什麼功能,策略表示如何使用這些功能。區分機制和策略是UNIX設計最重要和最好的思想之一。如X系統就由X伺服器和X用戶端組成。X伺服器實現機制,負責操作硬體,給使用者程式提供一個統一的介面。而X用戶端實現策略,負責如何使用X伺服器提供的功能。裝置驅動程式也是機制與策略分離的典型應用。在編寫硬體驅動程式時,不要強加任何特定的策略。
Linux系統將裝置分成三種類型,分別是字元裝置、塊裝置和網路介面裝置。
在linux中通過裝置檔案訪問硬體,裝置檔案位於/dev目錄下。裝置檔案是一種資訊檔,普通檔案的目的在於儲存資料,裝置檔案的目的在於向核心提供控制硬體的裝置驅動程式的資訊。裝置檔案儲存了多種資訊,其中重要的有裝置類型資訊,主裝置號(major),次裝置號(minor)。主裝置號與次裝置號起到串連應用程式和裝置驅動程式的作用。當應用程式利用open()函數開啟裝置檔案時,核心從相應的裝置檔案中得到主裝置號,從而尋找到相應的裝置驅動程式,由次裝置號尋找實際裝置。所以主裝置號對應裝置驅動程式,次裝置號對應由該驅動程式所驅動的實際裝置。通過裝置檔案可以向硬體傳送資料,也可從硬體接收資料。
裝置檔案使用mknod命令產生。mknod命令文法如下:
mknod [裝置檔案名稱] [裝置檔案類型] [主裝置號] [次裝置號]
字元裝置用c表示,塊裝置用b表示,網路裝置沒有專門的裝置檔案。
讀寫裝置檔案時要使用低級輸入輸出函數,不要使用帶緩衝的以f開頭的流檔案輸入輸出函數。但並不是所有低級輸入輸出函數都可以用在裝置檔案上,可以用在裝置檔案的低級輸入輸出函數有以下幾個:
open() 開啟檔案或裝置 close() 關閉檔案 read() 讀取資料 write() 寫資料 lseek() 改變檔案的讀寫位置 ioctl() 實現read(),write()外的特殊控制,該函數只在裝置檔案中使用 fsync() 實現寫入檔案上的資料和實際硬體的同步
Chapter 3. 字元裝置驅動程式3.1. 裝置號
字元裝置在系統中以裝置檔案的形式表示,位於/dev目錄下。每個字元裝置都有一個主裝置號和次裝置號,主裝置號標識裝置對應的驅動程式,次裝置號標識裝置檔案所指的具體裝置。
主次裝置號的資料類型是dev_t,在/linux/types.h中定義。在2.6核心中,dev_t是一個32位的數,其中12位用來表示主裝置號,其餘20位用來表示次裝置號。要獲得裝置的主次裝置號可以使用核心提供的宏:
MAJOR(dev_t dev); #獲得主裝置號 MINOR(dev_t dev); #獲得次裝置號
這些宏定義位於linux/kdev_t.h中。如果要把主次裝置號轉換成dev_t類型,則可使用:
MKDEV(int major, int minor);
3.2. 裝置號的分配和釋放
在建立一個字元裝置之前,需要為它分配一個或多個裝置號。使用register_chrdev_region()函數完成裝置號的分配。該函數在linux/fs.h中聲明。原型如下:
int register_chrdev_region(dev_t first, unsigned int count, char *name); first:是要分配的主裝置號範圍的起始值,次裝置號一般設定為0; count:是所請求的連續裝置號的個數; name:是和該裝置號範圍關聯的裝置名稱,它將出現在/proc/devices或/sysfs中。
如果分配成功則返回0,分配失敗則返回一個負的錯誤碼,所請求的裝置號無效。
還有一個自動分配裝置號的函數alloc_chrdev_region(),原型如下:
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name); dev: 自動分配到裝置號範圍中的第一個主裝置號; firstminor:自動分配的第一個次裝置號,通常為0; count: 是所請求的連續裝置號的個數; name: 是和該裝置號範圍關聯的裝置名稱,它將出現在/proc/devices或/sysfs中。
如果我們不再使用裝置號,則要使用unregister_chrdev_region()函數釋放它。函數原型如下:
void unregister_chrdev_region(dev_t first, unsigned int count); 函數的參數作用同上
我們一般在模組的清除函數中調用裝置號釋放函數。
在核心源碼目錄的Documentation/devices.txt檔案中列出了已靜態分配給常用裝置的主裝置號。為了減少裝置號分配的衝突,我們一般要使用alloc_chrdev_region()函數來自動分配裝置號。
3.3. 重要的資料結構
檔案操作結構:struct file_operations,在linux/fs.h中定義。它包含一組函數指標,實現檔案操作的系統調用,如read、write等。每個開啟的檔案都和一個檔案操作結構關聯(通過file結構中指向file_operations結構的f_op欄位進行關聯)。
檔案結構:struct file,在linux/fs.h中定義。file結構代表一個開啟的檔案,由核心在open時建立。指向檔案結構的指標在核心中通常稱為filp(檔案指標)。當檔案的所有執行個體都被關閉之後,核心會釋放這個資料結構。
節點結構:struct inode,在linux/fs.h中定義。inode結構是核心表示檔案的方法,而file結構是以檔案描述符的方式表示檔案的方法。結構中以下兩個欄位對編寫驅動程式有用:
從裝置的inode擷取主次裝置號的宏:
unsigned int iminor(struct inode *inode); unsigned int imajor(struct inode *inode);
3.4. 讀和寫
下面兩個是字元裝置讀寫操作最重要的核心功能。
unsigned long copy_to_user (void __user * to, const void * from, unsigned long n); 讀操作,把資料從核心空間複製到使用者空間,返回不能複製的位元組數,如果成功則返回0。 to 目的地址,在使用者空間中; from 源地址,在使用者空間; n 要複製的位元組數。 unsigned long copy_from_user (void * to, const void __user * from, unsigned long n); 寫操作,把資料從使用者空間複製到核心空間,返回不能複製的位元組數,如果成功則返回0。 to 目的地址,在核心空間中; from 源地址,在使用者空間; n 要複製的位元組數。