这篇文章主要是参考《linux内核设计与实现》,如果我直接把书中的内容贴过来当然可以解释这个题目。当然我不会这么做,我要做的是把重点列出来。vfs和sysfs不是设备模型的重点,没兴趣就不用看了。
先看VFS(原创的比较少)
文件系统
文件系统是个很模糊广泛的概念,"文件"狭义地说,是指磁盘文件,广义理解,可以是有组织有次序地存储与任何介质(包括内存)的一组信息。linux把所有的资源都看成是文件,让用户通过一个统一的文件系统操作界面,也就是同一组系统调用,对属于不同文件系统的文件进行操作。这样,就可以对用户程序隐藏各种不同文件系统的实现细节,为用户程序提供了一个统一的,抽象的,虚拟的文件系统界面,这就是所谓"VFS(Virtual Filesystem Switch)"。这个抽象出来的接口就是一组函数操作。
看图
从上图可以看到通过vfs可以访问各种各样的文件系统。这是因为它定义了所有文件系统都支持的基本的、概念上的接口和数据结构。同时实际的文件系统也将自身的诸如“如何打开文件”,“目录是什么”等概念在形式上与vfs的定义保持一致。和我们写驱动时为vfs提供open、write等方法很像。
看一个写的流程
vfs对象
四个代表。
超级块对象:代表一个已安装的文件系统。
索引节点对象:代表一个文件。
目录项对象:代表一个目录项,是路径的一个组成部分。
文件对象:代表由进程打开的文件。
目录作为一个文件来处理,不存在目录对象。目录项可能包括了一个文件,但目录就是一个文件。
四个操作。
super_operations对象:包括对特定文件系统的调用方法,比如read_inode()和sync_fs()。
inode_operations对象:包括对内核特定文件所能调用的方法,比如create()和link()。
dentry_operations对象:包括内核针对特定目录所能调用的方法,比如d_compare和d_delete()。
file_operations对象:包括进程针对已打开文件所能调用的方法,比如read()和write()。驱动常用这个。
超级块对象struct super_block:
对应于存储特定文件系统的信息(如文件系统类型、文件大小上限、设备标识符等),磁盘文件放在特定扇区中,特殊文件如sysfs放在内存中,掉电后完完了。
索引节点对象struct inode:
包含了内核在操作文件或目录时需要的全部信息。它表示文件类型、引用计数、访问时间等,如i_pipe表示是否为管道文件,还有i_device、i_cdev等。
目录项对象struct dentry:
什么是目录项对象,如路径/mnt/cdrom/foo,/,mnt,cdrom,foo都是目录项对象。目录项对象是为了查找方便。包含使用记录、子目录等。
文件对象struct file:
文件对象表示进程已打开的文件。用户看到最多的就是它,包含文件对象的使用计数、用户的UID和GID等。
和进程相关
每个进程都有自己的一组打开的文件,像根文件系统、当前工作目录、安装点等等。
主要的数据结构:
struct files_struct:所有与每个进程相关的信息。例如它包含一个struct file **fd指向已打开的文件对象链表。默认指向fs_array,默认一个数组容纳32个文件对象。超过将分配一个新的。
struct fs_struct: 文件系统和进程相关的信息。包含当前工作目录和根目录等。
struct namespace: 它使每个进程在系统中都看到惟一的安装文件系统。