基本概念 | 官方定义
VFS
(Virtual File System)是文件系统的虚拟层,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类Unix文件操作接口。由于不同类型的文件系统接口不统一,若系统中有多个文件系统类型,访问不同的文件系统就需要使用不同的非标准接口。而通过在系统中添加VFS层,提供统一的抽象接口,屏蔽了底层异构类型的文件系统的差异,使得访问文件系统的系统调用不用关心底层的存储介质和文件系统类型,提高开发效率。
OpenHarmony
内核中,VFS
框架是通过在内存中的树结构来实现的,树的每个结点都是一个Vnode
结构体,父子结点的关系以PathCache
结构体保存。VFS
最主要的两个功能是:
- 查找节点。
- 统一调用(标准)。
VFS
层具体实现包括四个方面:
- 通过三大函数指针操作接口,实现对不同文件系统类型调用不同接口实现标准接口功能;
- 通过
Vnode
与PathCache
机制,提升路径搜索以及文件访问的性能; - 通过挂载点管理进行分区管理;
- 通过FD管理进行进程间FD隔离等。
三大操作接口
VFS
层通过函数指针的形式,将统一调用按照不同的文件系统类型,分发到不同文件系统中进行底层操作。各文件系统的各自实现一套Vnode操作(VnodeOps
)、挂载点操作(MountOps
)以及文件操作接口(file_operations_vfs
),并以函数指针结构体的形式存储于对应Vnode
、挂载点、File
结构体中,实现VFS
层对下访问。这三个接口分别为:
VnodeOps | 操作 Vnode 节点
struct VnodeOps {
int (*Create)(struct Vnode *parent, const char *name, int mode, struct Vnode **vnode);//创建节点
int (*Lookup)(struct Vnode *parent, const char *name, int len, struct Vnode **vnode);//查询节点
//Lookup向底层文件系统查找获取inode信息
int (*Open)(struct Vnode *vnode, int fd, int mode, int flags);//打开节点
int (*Close)(struct Vnode *vnode);//关闭节点
int (*Reclaim)(struct Vnode *vnode);//回收节点
int (*Unlink)(struct Vnode *parent, struct Vnode *vnode, const char *fileName);//取消硬链接
int (*Rmdir)(struct Vnode *parent, struct Vnode *vnode, const char *dirName);//删除目录节点
int (*Mkdir)(struct Vnode *parent, const char *dirName, mode_t mode, struct Vnode **vnode);//创建目录节点
/*
创建一个目录时,实际做了3件事:在其“父目录文件”中增加一个条目;分配一个inode;再分配一个存储块,
用来保存当前被创建目录包含的文件与子目录。被创建的“目录文件”中自动生成两个子目录的条目,名称分别是:“.”和“..”。
前者与该目录具有相同的inode号码,因此是该目录的一个“硬链接”。后者的inode号码就是该目录的父目录的inode号码。
所以,任何一个目录的"硬链接"总数,总是等于它的子目录总数(含隐藏目录)加2。即每个“子目录文件”中的“..”条目,
加上它自身的“目录文件”中的“.”条目,再加上“父目录文件”中的对应该目录的条目。
*/
int (*Readdir)(struct Vnode *vnode, struct fs_dirent_s *dir);//读目录节点
int (*Opendir)(struct Vnode *vnode, struct fs_dirent_s *dir);//打开目录节点
int (*Rewinddir)(struct Vnode *vnode, struct fs_dirent_s *dir);//定位目录节点
int (*Closedir)(struct Vnode *vnode, struct fs_dirent_s *dir);//关闭目录节点
int (*Getattr)(struct Vnode *vnode, struct stat *st);//获取节点属性
int (*Setattr)(struct Vnode *vnode, struct stat *st);//设置节点属性
int (*Chattr)(struct Vnode *vnode, struct IATTR *attr);//改变节点属性(change attr)
int (*Rename)(struct Vnode *src, struct Vnode *dstParent, const char *srcName, const char *dstName);//重命名
int (*Truncate)(struct Vnode *vnode, off_t len);//缩减或扩展大小
int (*Truncate64)(struct Vnode *vnode, off64_t len);//缩减或扩展大小
int (*Fscheck)(struct Vnode *vnode, struct fs_dirent_s *dir);//检查功能
int (*Link)(struct Vnode *src, struct Vnode *dstParent, struct Vnode **dst, const char *dstName);
int (*Symlink)(struct Vnode *parentVnode, struct Vnode **newVnode, const char *path, const char *target);
ssize_t (*Readlink)(struct Vnode *vnode, char *buffer, size_t bufLen);
};