Linux設備驅動程序工作原理

        Linux是Unix操作系統的一種變種,在Linux下編寫驅動程序的原理和思想完全類似於其他的Unix系統。在Linux環境下設計驅動程序,思想簡潔,操作方便,功能也很強大,但是支持函數少,只能依賴kernel中的函數,有些常用的操作要自己來編寫,而且調試也不方便。 
  系統調用是操作系統內核和應用程序之間的接口,設備驅動程序是操作系統內核和機器硬件之間的接口。設備驅動程序爲應用程序屏蔽了硬件的細節,這樣在應用程序看來,硬件設備只是一個設備文件,應用程序可以象操作普通文件一樣對硬件設備進行操作。設備驅動程序是內核的一部分,運行在覈心態,它完成以下的功能:
  1.對設備初始化和釋放.
  2.把數據從內核傳送到硬件和從硬件讀取數據.
  3.讀取應用程序傳送給設備文件的數據和回送應用程序請求的數據.
  4.檢測和處理設備出現的錯誤.

  在Linux操作系統下有三類主要的設備文件類型:字符設備、塊設備和網絡接口。字符設備和塊設備的主要區別是:在對字符設備發出讀/寫請求時,實際的硬件I/O一般就緊接着發生了,塊設備則不然,它利用一塊系統內存作爲緩衝區,當用戶進程對設備請求能滿足用戶的要求,就返回請求的數據,如果不能,就調用請求函數來進行實際的I/O操作。塊設備是主要針對磁盤等慢速設備設計的,以免耗費過多的CPU時間來等待。
  已經提到,用戶進程是通過設備文件來與實際的硬件打交道。每個設備文件都有其文件屬性(c/b),表示是字符設備還是塊設備。另外每個文件都有兩個設備號,第一個是主設備號,標識驅動程序,第二個是從設備號,標識使用同一個設備驅動程序的不同的硬件設備,比如有兩個軟盤,就可以用從設備號來區分它們。設備文件的的主設備號必須與設備驅動程序在登記時申請的主設備號一致,否則用戶進程將無法訪問到驅動程序。
  由於用戶進程是通過設備文件同硬件打交道,對設備文件的操作方式不外乎就是一些系統調用,如 open,read,write,close...., 注意,不是fopen, fread,但是如何把系統調用和驅動程序關聯起來呢?這需要了解一個非常關鍵的數據結構:
struct file_operations {
int (*seek) (struct inode * ,struct file *, off_t ,int); 
int (*read) (struct inode * ,struct file *, char ,int); 
int (*write) (struct inode * ,struct file *, off_t ,int); 
int (*readdir) (struct inode * ,struct file *, struct dirent * ,int); 
int (*select) (struct inode * ,struct file *, int ,select_table *); 
int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long); 
int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *); 
int (*open) (struct inode * ,struct file *); 
int (*release) (struct inode * ,struct file *); 
int (*fsync) (struct inode * ,struct file *); 
int (*fasync) (struct inode * ,struct file *,int); 
int (*check_media_change) (struct inode * ,struct file *); 
int (*revalidate) (dev_t dev); 
} 

這個結構的每一個成員的名字都對應着一個系統調用。用戶進程利用系統調用在對設備文件進行諸如read/write操作時,系統調用通過設備文件的主設備號找到相應的設備驅動程序,然後讀取這個數據結構相應的函數指針,接着把控制權交給該函數,這是linux的設備驅動程序工作的基本原理。既然是這樣,則編寫設備驅動程序的主要工作就是編寫子函數,並填充file_operations的各個域。

深入分析:

       內核用struct inode結構在內部表示文件,因此它和struct file結構不同,後者用來描述被某個進程打開的文件。而且struct inodestruct file的一個成員。對單個文件,可能會有多個表示打開的文件描述結構體struct file,但是它們都指向單個struct inode結構。struct inode結構中包含了大量有關文件的信息,其中有一個重要的成員可以解釋清楚驅動程序的工作原理,這個成員爲:
dev_c i_rdev;//這個字段包含了正真的設備編號,包括主設備號和次設備號
內核用struct task_struct結構體來描述一個進程,在struct task_struct結構體中有一個重要成員:
struct files_struct *files;//描述了該進程打開的所有文件的信息
其定義如下:
struct files_struct{
int count;
fd_set close_on_exec;
fd_set open_fds;
struct file * fd[NR_OPEN];
};
fd就是由open系統調用返回的文件描述符,通過fd就可以找到對應的file結構,從而找到inode結構,再由inode結構找到i_rdev,也就是找到了設備文件的主設備號和次設備號。由於設備文件的主設備號標誌的是驅動程序,所以也就找到了已經在系統中註冊過的驅動程序。然後讀取struct file_operations中相應的標準系統調用的實現函數,從而完成了用戶的讀寫等的請求。調用鏈爲:
struct task_struct > struct files_stuctt > struct file > struct inode > i_rdev

注意:

開發驅動過程中,採用內核引用。/include下有很多頭文件,需要的只有/include/linux/include/asm目錄。

三個數據結構最重要:/linux/fs.h中定義的file_operationsinodefile結構。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章