inode and vnode

文件系统格式

windows: FAT, NTFS;
Linux: ext, ext1/2/3/4, xfs;
网络: NFS, SMB(samba SMB/CIFS)
云:

VFS: Linux & Mac OS 在文件系统之上虚拟出一层文件系统,Virtual FS;
POSIX: portable operating systerm interface of Unix.
来自用户进程的调用都通过POSIX系统调用(open, read, write, seek)接口来和底层文件系统(EXT, NTFS)交互;

比如同样是create, 在windows NTFS文件系统中用createprocess, 在UNIX中用fork, 那么虚拟层VFS中实现POSIX接口来统一它们的结构,方便和user space交互。

Vnode 是 virtual inode。
每个打开的文件或目录都有一个关联的vnode。是内存抽象的。
Vnode 包含有关文件的一些数据,但仅包含在文件生命周期内不会更改的属性
它抽象了 inode 的大部分内容(inode 可以是其数据字段之一),但也捕获了对文件、锁等的操作。
这使得它能够支持非基于 inode 的文件系统,特别是网络文件系统。

对于 vfs 类型,其虚函数表 struct vfsops,包含了一系列的函数指针,用来执行诸如 mount、unmount、sync 和 vget 等操作。
对于 vnode 类型也是类似的,其虚函数表 struct vnodeops,包含 open、rdwr 和 close 等函数,还有create、unlink 和 rename 等函数。一些函数是针对特定的文件类型的,比如 readlink、mkdir、readdir 和 rmdir。
vnode 实例用来进行跟踪打开的文件。它包含 struct *vnodeops 指针

inode 和 vnode的理解

inode 指的是文件的元数据,是文件系统层面的结构,在数据块中的物理位置,存在于具体的文件系统中,只对具体的文件系统有意义:

NTFS, FAT, ext3, xfs, NFS, SMBAFS
inode 本身不存储文件名

vnode 是 unit-like操作系统中的抽象层,为不同文件系统提供统一的接口。

用于代表所有文件系统的文件或目录,包含指向具体文件系统操作的指针。
可以统一的处理各种文件系统。

每个打开的文件或目录都有一个关联的vnode。是内存抽象的。
Vnode 包含有关文件的一些数据,但仅包含在文件生命周期内不会更改的属性

vnode 本身不存储文件名

inode 是文件系统级别的,vnode是操作系统级别的,为所有文件系统提供一个统一的接口
vnode只在文件打开时候才会存在,它调用inode的信息,但是windows怎么做呢?

inode

是unix中文件的元数据,包含:
软、硬链接;
owner, group;
ACLs;
数据块指针;

ls -le 中的数据几乎都是从inode来的

vnode

表示文件的抽象接口,指向文件?
当应用程序请求打开文件, 内核查找如果缓存中没有的话,就会创建一个vnode。
然后开始填充vnode,查看请求的文件路径位于哪个文件系统上,如果在linux上,就用linux的
文件系统驱动来填充? 怎么理解这里的文件系统驱动?
如果位于NTFS,就用ntfs的驱动。。

当应用程序要读文件时候,使用vnode的信息,函数指针,进行操作。

扩展

inode 指向数据块的指针

硬链接两个文件名,指向同一份文件data;
多个文件名 指向同一个文件data;

软连接可以跨文件系统,类似于 Windows 的快捷方式;

用 ln filename hardfilename, 创建一个硬链接;
用ls -li 查看源文件和硬链接都有相同的inode,指向同一个物理数据块;
修改hardfilename内容,查看源文件,内容显示的也是修改后的;

https://www.jianshu.com/p/dde6a01c4094

ln -s 创建一个软连接,发现它指向的inode与源文件不同, 软连接的inode中指向的数据块中存放的是源文件的路径;

删除源文件之后,读取硬链接,发现内容还在,因为硬链接的inode 依然指向那个data block,data block并未被释放掉;
而软连接找不到内容,因为软连接指向的绝对路径源文件被删了;

再扩展 文件描述符

https://www.cnblogs.com/jiangzhaowei/p/4154834.html
当进程打开一个文件时,内核就会创建一个新的file对象;
file对象中描述了文件的打开模式,读写位置等重要信息;
file对象不是专属于某个进程的,不同进程的文件描述符表中的指针可以指向相同的file对象,从而共享这个打开的文件;
file对象有引用计数,记录了引用这个对象的文件描述符个数,只有当引用计数为0时,内核才销毁file对象,
因此某个进程关闭文件,不影响与之共享同一个file对象的进程.

dentry对象代表一个独立的文件路径,如果一个文件路径被打开多次,那么会建立多个file对象,但它们都指向同一个dentry对象。
dentry对象中又包含一个指向inode对象的指针。inode对象代表一个独立文件。因为存在硬链接与符号链接,因此不同的dentry对象可以指向相同的inode对象.
inode 对象包含了最终对文件进行操作所需的所有信息,如文件系统类型、文件的操作方法、文件的权限、访问日期等。

来到vnode的扩展部分

https://juicefs.com/zh-cn/blog/engineering/how-support-multiple-file-systems

对于 vfs 类型,其虚函数表 struct vfsops,包含了一系列的函数指针,用来执行诸如 mount、unmount、sync 和 vget 等操作。
对于 vnode 类型也是类似的,其虚函数表 struct vnodeops,包含 open、rdwr 和 close 等函数,还有create、unlink 和 rename 等函数。一些函数是针对特定的文件类型的,比如 readlink、mkdir、readdir 和 rmdir。
vnode 实例用来进行跟踪打开的文件。它包含 struct *vnodeops 指针

我们可以在此处找到文件对象,struct file 的实例。在文件的所有其他内容中,最值得注意的是一个字段 loff_t f_pos,它表示文件当前位置距离文件起始位置的偏移量(以字节为单位)。

文件的类是通过一个虚函数表来定义。我们可以找到一个指针 struct file_operations *f_op 。
它展示了文件可以执行的所有操作,其中最常见的是打开(open)、关闭(close)、定位(lseek)、读取(read)和写入(write)。
https://wushifublog.com/2020/05/22/深入理解Linux内核——VFS/

扩展: poxis中的文件锁

POSIX 标准是要求通过 fcntl() 系统调用实现一个文件锁的机制,这样就能避免竞争关系。
这个文件锁可以对整个文件或者文件中的某个区域(小到一个字节)进行锁定,由于可以锁文件的部分内容,所以一个进程可以同时获取同一个文件的多个锁。

在 Linux 中可以通过 fcntl() & flock() 系统调用对文件进行上锁。通常在类 unix 系统中,flock() 系统调用会无视 MS_MANDLOCK 的挂载标志,只产生劝告锁。

Linux 对于劝告锁和强制锁都有实现。一个进程获取劝告锁的方式有2种:

通过 flock() 系统调用,这个锁只能对整个文件上锁
通过 fcntl() 系统调用,可以文件的特定部分进行上锁

posted @ 2024-06-23 14:02  vivi~  阅读(4)  评论(3编辑  收藏  举报