每个进程在PCB(Process Control Block)中都保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针,现在我们明确一下:已打开的文件在内核中用file
结构体表示,文件描述符表中的指针指向file
结构体。
在file
结构体中维护File Status Flag(file
结构体的成员f_flags
)和当前读写位置(file
结构体的成员f_pos
)。在上图中,进程1和进程2都打开同一文件,但是对应不同的file
结构体,因此可以有不同的File Status Flag和读写位置。file
结构体中比较重要的成员还有f_count
,表示引用计数(Reference Count),后面我们会讲到,dup
、fork
等系统调用会导致多个文件描述符指向同一个file
结构体,例如有fd1
和fd2
都引用同一个file
结构体,那么它的引用计数就是2,当close(fd1)
时并不会释放file
结构体,而只是把引用计数减到1,如果再close(fd2)
,引用计数就会减到0同时释放file
结构体,这才真的关闭了文件。
每个file
结构体都指向一个file_operations
结构体,这个结构体的成员都是函数指针,指向实现各种文件操作的内核函数。比如在用户程序中read
一个文件描述符,read
通过系统调用进入内核,然后找到这个文件描述符所指向的file
结构体,找到file
结构体所指向的file_operations
结构体,调用它的read
成员所指向的内核函数以完成用户请求。在用户程序中调用lseek
、read
、write
、ioctl
、open
等函数,最终都由内核调用file_operations
的各成员所指向的内核函数完成用户请求。file_operations
结构体中的release
成员用于完成用户程序的close
请求,之所以叫release
而不叫close
是因为它不一定真的关闭文件,而是减少引用计数,只有引用计数减到0才关闭文件。对于同一个文件系统上打开的常规文件来说,read
、write
等文件操作的步骤和方法应该是一样的,调用的函数应该是相同的,所以图中的三个打开文件的file
结构体指向同一个file_operations
结构体。如果打开一个字符设备文件,那么它的read
、write
操作肯定和常规文件不一样,不是读写磁盘的数据块而是读写硬件设备,所以file
结构体应该指向不同的file_operations
结构体,其中的各种文件操作函数由该设备的驱动程序实现。
每个file
结构体都有一个指向dentry
结构体的指针,“dentry”是directory entry(目录项)的缩写。我们传给open
、stat
等函数的参数的是一个路径,例如/home/akaedu/a
,需要根据路径找到文件的inode。为了减少读盘次数,内核缓存了目录的树状结构,称为dentry cache,其中每个节点是一个dentry
结构体,只要沿着路径各部分的dentry搜索即可,从根目录/
找到home
目录,然后找到akaedu
目录,然后找到文件a
。dentry cache只保存最近访问过的目录项,如果要找的目录项在cache中没有,就要从磁盘读到内存中。
每个dentry
结构体都有一个指针指向inode
结构体。inode
结构体保存着从磁盘inode读上来的信息。在上图的例子中,有两个dentry,分别表示/home/akaedu/a
和/home/akaedu/b
,它们都指向同一个inode,说明这两个文件互为硬链接。inode
结构体中保存着从磁盘分区的inode读上来信息,例如所有者、文件大小、文件类型和权限位等。每个inode
结构体都有一个指向inode_operations
结构体的指针,后者也是一组函数指针指向一些完成文件目录操作的内核函数。和file_operations
不同,inode_operations
所指向的不是针对某一个文件进行操作的函数,而是影响文件和目录布局的函数,例如添加删除文件和目录、跟踪符号链接等等,属于同一文件系统的各inode
结构体可以指向同一个inode_operations
结构体。
inode
结构体有一个指向super_block
结构体的指针。super_block
结构体保存着从磁盘分区的超级块读上来的信息,例如文件系统类型、块大小等。super_block
结构体的s_root
成员是一个指向dentry
的指针,表示这个文件系统的根目录被mount
到哪里,在上图的例子中这个分区被mount
到/home
目录下。
file
、dentry
、inode
、super_block
这几个结构体组成了VFS的核心概念。对于ext2文件系统来说,在磁盘存储布局上也有inode和超级块的概念,所以很容易和VFS中的概念建立对应关系。而另外一些文件系统格式来自非UNIX系统(例如Windows的FAT32、NTFS),可能没有inode或超级块这样的概念,但为了能mount
到Linux系统,也只好在驱动程序中硬凑一下,在Linux下看FAT32和NTFS分区会发现权限位是错的,所有文件都是rwxrwxrwx
,因为它们本来就没有inode和权限位的概念,这是硬凑出来的。
补充:
在这个图上没有反应file_operations与inode的关系,特去查看了源码(/usr/include/fs.h)知
/*
* Note that nosuid etc flags are inode-specific: setting some file-system
* flags just means all the inodes inherit those flags by default. It might be
* possible to override it selectively if you really wanted to with some
* ioctl() that is not currently implemented.
*
* Exception: MS_RDONLY is always applied to the entire file system.
*
* Unfortunately, it is possible to change a filesystems flags with it mounted
* with files in use. This means that all of the inodes will not have their
* i_flags updated. Hence, i_flags no longer inherit the superblock mount
* flags, so these have to be checked separately. -- rmk@arm.uk.linux.org
*/
#define __IS_FLG(inode,flg) ((inode)->i_sb->s_flags & (flg))
#define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY)
#define IS_SYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS) || \
((inode)->i_flags & S_SYNC))
#define IS_DIRSYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || \
((inode)->i_flags & (S_SYNC|S_DIRSYNC)))
#define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK)
#define IS_NOATIME(inode) __IS_FLG(inode, MS_RDONLY|MS_NOATIME)
#define IS_I_VERSION(inode) __IS_FLG(inode, MS_I_VERSION)
#define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA)
#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND)
#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
#define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL)
#define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
#define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
#define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE)
#define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE)
#define IS_IMA(inode) ((inode)->i_flags & S_IMA)
#define IS_AUTOMOUNT(inode) ((inode)->i_flags & S_AUTOMOUNT)
#define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC)
file_operations结构体中每个函数指针所指向的操作函数都是需要传进一个inode表项结构体的.
分享到:
相关推荐
5. **文件系统操作向量(File System Operations,简称VFS Ops)**:这是VFS的核心,是一组函数指针,定义了对文件系统的基本操作,如打开、关闭、读写等。 `vfs.c`是Linux内核源码中实现VFS功能的主要文件,它包含...
5. **文件操作结构体(File Operations Structure)**:定义了一组函数指针,用于处理与文件相关的操作,如读写、关闭、重命名等。 VFS的工作流程大致如下: 1. **打开文件**:用户通过路径名请求打开文件,VFS...
### 文件结构体 (`struct file`) 与 索引节点结构体 (`struct inode`) #### 一、`struct file` 结构体 `struct file` 是 Linux 内核中的一个重要数据结构,它用来描述内核空间中每一个打开的文件。这个结构体在 `...
当通过VFS操作`struct file`时,会通过`inode_operations`和`file_operations`结构将操作映射到特定文件系统的方法。例如,读写操作会通过`inode_operations`中的`read_inode`和`write_inode`等函数进行。 4. **...
`dentry` (Directory Entry) 用于表示文件系统中的目录项,它是文件名与其对应 `inode` 的映射关系。 ```c struct dentry { atomic_t d_count; struct inode *d_inode; struct hlist_node d_hash; struct ...
VFS(Virtual File System)是Linux操作系统中至关重要的组成部分,它提供了一种抽象层,使得各种不同的文件系统能够共存并交互。通过VFS,Linux内核能够支持多种类型的文件系统,无需关心底层的具体实现。VFS的核心...
VFS_full.rar_VFS_full 是一个与操作系统内核相关的压缩包,主要包含C++编程的文件,特别是针对操作系统中的虚拟文件系统(Virtual File System, VFS)进行编程的代码。虚拟文件系统是现代操作系统中非常关键的一个...
最后通过`insert_inode_hash`函数将其插入到inode哈希表中。 - **inode操作集**: ```c if (S_ISREG(inode->i_mode)) { inode->i_fop = &generic_ro_fops; inode->i_data.a_ops = &cramfs_aops; } else if (S_...
3. **文件操作结构体**:在VFS中,每个文件系统都有一个`file_operations`结构体,其中包含了文件的各种操作函数指针。例如,读写操作会通过`op->read`和`op->write`指针调用到具体文件系统的实现。 4. **VFS数据...
VFS的核心组成部分包括超级块(superblock)、索引节点(inode)和文件操作结构(file_operations)。超级块是VFS用来记录每个已挂载文件系统基本信息的数据结构,包含了文件系统的类型、大小、状态等信息。当一个新...
- VFS通过`inode_operations`和`file_operations`结构体定义了对文件和inode的操作,如读写、打开、关闭等。实际文件系统实现这些操作的具体逻辑,VFS作为中间层进行调度。 6. **内存管理** - VFS目录树的数据...
16. 每个已安装的文件系统由一个 VFS 超块表示它包含如下信息:Device、Inode pointers、Blocksize、Superblock operations、File System type、File System specific。 17. VFS inode 是一种抽象的表示文件或目录的...
本章主要探讨的是Linux内核源代码中关于文件系统的分析,特别是虚拟文件系统(Virtual File System, VFS)及其与具体文件系统之间的关系。 1. **虚拟文件系统(VFS)**: VFS是Linux内核提供的一种抽象层,它统一...
VFS 会根据 file_operations 中的 `open` 函数指针调用实际文件系统的打开函数。类似地,当应用程序调用 `read()` 函数读取文件时,内核会执行 `sys_read` 系统调用。VFS 会查找相应的 file_operations,并调用其中...
`struct cdev`与`struct file_operations`之间的关联是通过`cdev_init()`函数建立的,它将设备的操作函数表绑定到字符设备结构中。`cdev_alloc()`分配一个新的`cdev`结构体,`cdev_put()`回收空间,`cdev_del()`注销...
Linux内核设计与实现中的VFS(Virtual File System,虚拟文件系统)机制是操作系统的核心组件之一,它为用户空间的应用程序提供了一种统一、抽象的文件访问方式,无需关心底层的具体文件系统类型。VFS的设计使得...
const struct inode_operations ext4_dir_inode_operations = { .create = ext4_create, .lookup = ext4_lookup, .link = ext4_link, .unlink = ext4_unlink, .symlink = ext4_symlink, .mkdir = ext4_mkdir, ...
### Linux VFS(虚拟文件系统)概述与内核源代码分析 #### VFS的作用与重要性 Linux VFS,即虚拟文件系统,是Linux内核中的一个关键组件,它为不同的文件系统提供了一套统一的接口。VFS的存在使得Linux能够支持...
2. `f_dentry`:指向文件的`dentry`结构,`dentry`存储文件系统的文件名和其对应的inode(文件的内核表示)的映射关系。 3. `f_vfsmnt`:指针指向文件所在的VFS(虚拟文件系统)挂载点,用于识别文件系统类型。 4. `...