Linux Kernel學習筆記

來源:互聯網
上載者:User

標籤: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結構是以檔案描述符的方式表示檔案的方法。結構中以下兩個欄位對編寫驅動程式有用:

  • dev_t i_rdev,該欄位包含了真正的裝置編號。

  • struct cdev *i_cdev,該欄位包含指向struct cdev結構的指標。

從裝置的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 要複製的位元組數。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.