您的位置:首页 > 运维架构 > Linux

[快速上手Linux设备驱动]之一切皆是文件思想

2012-12-13 22:42 246 查看
只要用过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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LINUX 文件操作