只要用過linux的筒子,或者保守點說接觸到一些linux思想的同志肯定聽說過這樣一句話,在linux下,「一切皆是檔案」!
不錯,今天walfred將在快速上手linux裝置驅動這一塊,談談linux的裝置也符合「一切皆是檔案」的思想在linux裝置驅動模型應用。如果你不理解linux裝置模型,請看下面:
1.[快速上手linux裝置驅動]之我看linux裝置模型(匯流排篇)
2.[快速上手linux裝置驅動]之我看linux裝置模型(裝置篇)
3.[快速上手linux裝置驅動]之我看linux裝置模型(裝置驅動篇)
4.[快速上手linux裝置驅動]之我看linux裝置模型(類子系統篇)
「一切皆是檔案」是 unix/linux 的基本哲學之一。不僅普通的檔案,目錄、字元裝置、塊裝置、 套接字等在 unix/linux 中都是以檔案被對待;它們雖然型別不同,但是對其提供的卻是同一套操作介面。
當然,在這裡我先給大家上一道預備知識的大菜,不過這邊我先暫時小打小鬧下,稍微說下,日後詳述之。
有請vfs上場--
虛擬檔案系統(virtual file system, 簡稱 vfs), 是 linux 核心中的乙個軟體層,用於給使用者空間的程式提供檔案系統介面;同時,它也提供了核心中的乙個抽象功能,允許不同的檔案系統共存。系統中所有的檔案系統不但依賴 vfs 共存,而且也依靠 vfs 協同工作。
為了能夠支援各種實際檔案系統,vfs 定義了所有檔案系統都支援的基本的、概念上的介面和資料 結構;同時實際檔案系統也提供 vfs 所期望的抽象介面和資料結構,將自身的諸如檔案、目錄等概念在形式 上與vfs的定義保持一致。換句話說,乙個實際的檔案系統想要被 linux 支援,就必須提供乙個符合vfs標準 的介面,才能與 vfs 協同工作。實際檔案系統在統一的介面和資料結構下隱藏了具體的實現細節,所以在vfs 層和核心的其他部分看來,所有檔案系統都是相同的。下圖顯示了vfs在核心中與實際的檔案系統的協同關係。
正文
從上圖,我們可以簡單的看出乙個在user space的應用程式通過系統呼叫,經過vfs層面,在和裝置驅動打交道,最後裝置驅動驅動對應裝置,這是乙個比較簡單的描述,如果分析起來也就不難得到:user space的應用程式與vfs的介面就是系統呼叫,vfs與驅動程式的介面就是file_operations。
關於file_operations
從之前打過交道的字元裝置驅動,我們就知道存在了這麼一種file_operations結構體,我現在可以說在描述乙個裝置,我們使用者最接近的方法是file_operations,linux每類裝置都定義了檔案操作方法,例如,字元裝置的操作方法為def_chr_fops,塊裝置為def_blk_fops,網路裝置為bad_sock_fops。每種裝置型別底層操作方法是不一樣的,但是通過file_operations方法將裝置型別的差異化遮蔽了,這就是linux能夠將所有裝置都理解為檔案的緣由。這裡因為我這幾天在搞塊裝置,所以先看下def_blk_fops。
struct file_operations def_blk_fops = {
open: blkdev_open,
release: blkdev_close,
llseek: block_llseek,
read: generic_file_read,
write: generic_file_write,
mmap: generic_file_mmap,
fsync: block_fsync,
ioctl: blkdev_ioctl,
裝置差異性
到這裡,又提出乙個問題:既然這樣,那裝置的差異化又該如何體現呢?在檔案系統層定義了檔案系統訪問裝置的方法,該方法就是address_space_operations,檔案系統通過該方法可以訪問具體的裝置。對於字元裝置而言,沒有實現address_space_operations方法,也沒有必要,因為字元裝置的介面與檔案系統的介面是一樣的,在字元裝置open操作的過程中,將inode所指向的file_operations替換成cdev所指向的file_operations就可以了。這樣使用者層讀寫字元裝置可以直接呼叫cdev中file_operations方法了。
[linux/fs.h]
*linux頁快取記憶體實用化address_space結構體描述頁快取記憶體中的頁面
*定義檔案在linux/fs.h中
struct address_space {
struct inode *host; /* 擁有節點 */
struct radix_tree_root page_tree; /* 包含全部頁面的radix樹 */
spinlock_t tree_lock; /* 保護page_tree的自旋鎖 */
unsigned int i_mmap_writable; /* vm_shared記數 */
struct prio_tree_root i_mmap; /* 似有對映鍊錶 */
struct list_head i_mmap_nonlinear; /* vm_nonlinear鍊錶 */
spinlock_t i_mmap_lock; /* 保護i_mmap的自旋鎖 */
atomic_t truncate_count; /* 截斷記數 */
unsigned long nrpages; /* 頁總數 */
pgoff_t writeback_index; /* 回寫的起始偏移 */
struct address_space_operations *a_ops; /* 操作表*/
unsigned long flags; /* gfp_mask掩碼與錯誤標識 */
struct backing_dev_info *backing_dev_info; /* 預讀資訊 */
spinlock_t private_lock; /* 私有address_space鎖 */
struct list_head private_list; /* 私有address_space鍊錶 */
struct address_space_operations {
int (*writepage)(struct page *, struct writeback_control *);
int (*readpage) (struct file *, struct page *);
int (*sync_page) (struct page *);
int (*writepages) (struct address_space *, struct writeback_control *);
int (*set_page_dirty) (struct page *);
int (*readpages) (struct file *, struct address_space *,
struct list_head *, unsigned);
int (*prepare_write) (struct file *, struct page *, unsigned, unsigned);
int (*commit_write) (struct file *, struct page *, unsigned, unsigned);
sector_t (*bmap)(struct address_space *, sector_t);
int (*invalidatepage) (struct page *, unsigned long);
int (*releasepage) (struct page *, int);
int (*direct_io) (int, struct kiocb *, const struct iovec *,
loff_t, unsigned long);
到這裡,是不是明白了linux的「裝置」也是檔案了呢?
塊裝置驅動程式之一
linux支援的兩種重要的裝置型別分別是字元裝置和塊裝置,塊裝置可以隨機地以固定大小的塊傳送資料。與字元裝置相比,塊裝置有以下幾個特殊之處 塊裝置可以從資料的任何位置進行訪問 塊資料總是以固定長度進行傳輸,即便請求的這是乙個位元組 對塊裝置的訪問有大量的快取。當進行讀時,如果已經快取了,就直接使用快...
Linux課堂筆記之一簡單上手
a 登陸centos 1 首次登陸的時候選擇語言,選擇中文 2 為了安全使用用兩個賬號,乙個管理者的賬號,乙個普通賬號 3 linux有圖形介面和文字介面,預設登陸的是gnome b gnome 1 控制面板 2 桌面 3 下方工作列 4 資源管理器 鸚鵡螺 5 切換中文輸入法 ctrl space...
Linux字元裝置驅動 一
inux字元裝置驅動之概述篇 一.概述 1.在linux中有一句哲學 linux下皆檔案 裝置驅動程式為應用程式遮蔽了硬體的細節,這樣在應用程式看來,硬體裝置只是乙個裝置檔案,應用程式可以像操作普通檔案一樣對硬體裝置進行操作。但是裝置檔案和普通檔案還是又差別的。那麼裝置和普通檔案之間又有什麼區分呢?...