[快速上手Linux設備驅動]之一切皆是文件思想

只要用過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    *assoc_mapping;     /* 相關的緩衝 */

};

/*

*/

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的“設備”也是文件了呢?

原文地址:http://www.ourunix.org/post/157.html

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