文件系统抽象层VFS
文件系统抽象层是把不同文件系统的对外共性接口提取出来,形成一个函数指针数组,这样,通用文件系统访问接口层只需访问文件系统抽象层,而不需关心具体文件系统的实现细节和接口。
file&dir接口
file&dir 接口层定义了进程在内核中直接访问的文件相关信息,这定义在 file 数据结构中,具体描述如下:
// kern/fs/file.h
struct file {
enum {
FD_NONE, FD_INIT, FD_OPENED, FD_CLOSED,
} status; //访问文件的执行状态
bool readable; //文件是否可读
bool writable; //文件是否可写
int fd; //文件在filemap中的索引值
off_t pos; //访问文件的当前位置
struct inode *node; //该文件对应的内存inode指针
int open_count; //打开此文件的次数
};而在 kern/process/proc.h中的 proc_struct 结构中加入了描述了进程访问文件的数据接口 files_struct,其数据结构定义如下:
// kern/fs/fs.h
struct files_struct {
struct inode *pwd; //进程当前执行目录的内存inode指针
struct file *fd_array; //进程打开文件的数组
atomic_t files_count; //访问此文件的线程个数
semaphore_t files_sem; //确保对进程控制块中fs_struct的互斥访问
};当创建一个进程后,该进程的 files_struct 将会被初始化或复制父进程的 files_struct。当用户进程打开一个文件时,将从 fd_array 数组中取得一个空闲 file 项,然后会把此 file 的成员变量 node 指针指向一个代表此文件的 inode 的起始地址。
inode接口
index node 是位于内存的索引节点,它是 VFS 结构中的重要数据结构,因为它实际负责把不同文件系统的特定索引节点信息(甚至不能算是一个索引节点)统一封装起来,避免了进程直接访问具体文件系统。其定义如下:
在 inode 中,有一成员变量为 in_ops,这是对此 inode 的操作函数指针列表,其数据结构定义如下:
参照上面对 SFS 中的索引节点操作函数的说明,可以看出 inode_ops 是对常规文件、目录、设备文件所有操作的一个抽象函数表示。对于某一具体的文件系统中的文件或目录,只需实现相关的函数,就可以被用户进程访问具体的文件了,且用户进程无需了解具体文件系统的实现细节。
open系统调用的执行过程
下面我们通过打开文件的系统调用open()的执行过程, 看看文件系统的不同层次是如何交互的。
首先,经过syscall.c的处理之后,进入内核态,执行sysfile_open()函数
可以看到,sysfile_open 把路径复制了一份,然后调用了file_open, file_open调用了vfs_open, 使用了VFS的接口。
vfs_open是一个比较复杂的函数,这里我们使用的打开文件的flags, 基本是参照linux,如果希望详细了解,可以阅读linux manual: open。
我们看看vfs_look_up的实现
我们注意到,这个流程中,有大量以vop开头的函数,它们都通过一些宏和函数的转发,最后变成对inode结构体里的inode_ops结构体的“成员函数”(实际上是函数指针)的调用。对于SFS文件系统的inode来说,会变成对sfs文件系统的具体操作。sfs的这些具体接口的实现较为繁琐,可以在kern/fs/sfs/sfs_inode.c具体查看。我们的练习要求在kern/fs/sfs/sfs_io.c填写一个函数。
最后更新于
这有帮助吗?