vfs重要数据结构
superblock object
struct super_block {
/**
* 指向超级块链表的指针
*/
struct list_head s_list; /* Keep this first */
/**
* 设备标识符
*/
dev_t s_dev; /* search index; _not_ kdev_t */
/**
* 以字节为单位的块大小
*/
unsigned long s_blocksize;
/**
* 基本块设备驱动程序中的以字节为单位的块大小。
*/
unsigned long s_old_blocksize;
/**
* 以位为单位的块大小
*/
unsigned char s_blocksize_bits;
/**
* 脏标志
*/
unsigned char s_dirt;
/**
* 文件的最大长度
*/
unsigned long long s_maxbytes; /* Max file size */
/**
* 文件系统类型。
*/
struct file_system_type *s_type;
/**
* 超级块方法
*/
struct super_operations *s_op;
/**
* 磁盘限额处理方法
*/
struct dquot_operations *dq_op;
/**
* 磁盘限额管理方法
*/
struct quotactl_ops *s_qcop;
/**
* NFS使用的输出操作
*/
struct export_operations *s_export_op;
/**
* 安装标志
*/
unsigned long s_flags;
/**
* 文件系统的魔数
*/
unsigned long s_magic;
/**
* 文件系统根目录的目录项
*/
struct dentry *s_root;
/**
* 卸载时使用的信号量
*/
struct rw_semaphore s_umount;
/**
* 保护超级块使用的信号量
*/
struct semaphore s_lock;
/**
* 引用计数
*/
int s_count;
/**
* 对超级块的索引节点进行同步的标志
*/
int s_syncing;
/**
* 对超级块的已安装文件系统进行同步的的标志
*/
int s_need_sync_fs;
/**
* 次引用计数。
*/
atomic_t s_active;
/**
* 超级块安全数据结构
*/
void *s_security;
/**
* 超级块扩展属性结构的指针
*/
struct xattr_handler **s_xattr;
/**
* 所有索引节点链表
*/
struct list_head s_inodes; /* all inodes */
/**
* 脏索引节点链表
*/
struct list_head s_dirty; /* dirty inodes */
/**
* 等等写入磁盘的索引节点链表
*/
struct list_head s_io; /* parked for writeback */
/**
* 匿名目录项链表,用于NFS
*/
struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */
/**
* 文件对象链表
*/
struct list_head s_files;
/**
* 指向块设备驱动程序描述符的指针
*/
struct block_device *s_bdev;
/**
* 相同文件类型的超级块对象链表。
*/
struct list_head s_instances;
/**
* 磁盘限额的描述符
*/
struct quota_info s_dquot; /* Diskquota specific options */
/**
* 冻结文件系统时使用的标志,用于强制设置一致性状态。
*/
int s_frozen;
/**
* 等待解冻的队列。
*/
wait_queue_head_t s_wait_unfrozen;
/**
* 包含超级块的块设备名称
*/
char s_id[32]; /* Informational name */
/**
* 指向特定文件系统的超级块信息的指针。各文件系统自定义。
* 对ext2来说,是指向一个ext2_sb_info类型的结构。
*/
void *s_fs_info; /* Filesystem private info */
/*
* The next field is for VFS *only*. No filesystems have any business
* even looking at it. You had been warned.
*/
/**
* 当VFS通过目录重命名文件时使用的信号量。
*/
struct semaphore s_vfs_rename_sem; /* Kludge */
/* Granuality of c/m/atime in ns.
Cannot be worse than a second */
/**
* c/m/atime的时间戳粒度。
*/
u32 s_time_gran;
};
superblock operation tables
/**
* 超级块操作方法
*/
struct super_operations {
/**
* 为索引节点对象分配空间,包括具体文件系统的数据所需要的空间。
*/
struct inode *(*alloc_inode)(struct super_block *sb);
/**
* 释放索引节点对象。
*/
void (*destroy_inode)(struct inode *);
/**
* 用磁盘上的数据填充索引节点对象的字段。
* 索引节点对象的i_ino字段标识从磁盘上要索引节点。
*/
void (*read_inode) (struct inode *);
/**
* 当索引节点标记为脏时调用。日志文件系统用来更新磁盘上的文件系统日志。
*/
void (*dirty_inode) (struct inode *);
/**
* 更新索引节点对象的内容。flag参数表示IO操作是否应当同步。
*/
int (*write_inode) (struct inode *, int);
/**
* 减少索引节点的引用计数值。
*/
void (*put_inode) (struct inode *);
/**
* 当最后一个用户释放索引节点时调用。通常调用generic_drop_inode。
*/
void (*drop_inode) (struct inode *);
/**
* 删除内存中的索引节点和磁盘上的文件数据和元数据。
*/
void (*delete_inode) (struct inode *);
/**
* 由于文件系统被卸载而释放对超级块的引用。
*/
void (*put_super) (struct super_block *);
/**
* 更新文件系统超级块。
*/
void (*write_super) (struct super_block *);
/**
* 清除文件系统以更新磁盘上文件系统数据结构
*/
int (*sync_fs)(struct super_block *sb, int wait);
/**
* 阻塞对文件系统的修改,并用指定对象的内容更新超级块。
* 当文件系统被冻结时调用。例如LVM会调用它。
*/
void (*write_super_lockfs) (struct super_block *);
/**
* 取消由write_super_lockfs阻塞。
*/
void (*unlockfs) (struct super_block *);
/**
* 返回文件系统的统计信息。
*/
int (*statfs) (struct super_block *, struct kstatfs *);
/**
* 用新的选项重新安装文件系统。
*/
int (*remount_fs) (struct super_block *, int *, char *);
/**
* 撤销磁盘索引节点时调用。
*/
void (*clear_inode) (struct inode *);
/**
* 开始卸载操作。只在NFS中使用。
*/
void (*umount_begin) (struct super_block *);
/**
* 显示特定文件系统的选项。
*/
int (*show_options)(struct seq_file *, struct vfsmount *);
/**
* 读取限额设置。
*/
ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
/**
* 修改限额配置。
*/
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
};
inode object
The inode object represents all the information needed by the kernel to manipulate a file or directory.
The inode object is represented by struct inode and is defined in <linux/fs.h>
/**
* 内核用该结构在内部表示一个文件。它与file不同。file表示的的文件描述符。
* 对单个文件,可能会有许多个表示打开的文件描述符的filep结构,但是它们都指向单个inode结构。
*/
struct inode {
/**
* 通过此字段将对象放入哈希表。
*/
struct hlist_node i_hash;
/**
* 通过此字段将队列链入不同状态的链表中。
*/
struct list_head i_list;
/**
* 通过此字段将其链入到超级块的inode链表中。
*/
struct list_head i_sb_list;
/**
* 引用索引节点的目录项对象链表头。
*/
struct list_head i_dentry;
/**
* 索引节点编号。
*/
unsigned long i_ino;
/**
* 引用计数器。
*/
atomic_t i_count;
/**
* 文件类型与访问权限。
*/
umode_t i_mode;
/**
* 硬链接数目。
*/
unsigned int i_nlink;
/**
* 所有者ID
*/
uid_t i_uid;
/**
* 所有者组标识符。
*/
gid_t i_gid;
/**
* 对表示设备文件的inode结构,该字段包含了真正的设备编号。
*/
dev_t i_rdev;
/**
* 文件的字节数。
*/
loff_t i_size;
/**
* 上次访问文件的时间。
*/
struct timespec i_atime;
/**
* 上次与文件的时间。
*/
struct timespec i_mtime;
/**
* 上次修改索引节点的时间。
*/
struct timespec i_ctime;
/**
* 块的位数。
*/
unsigned int i_blkbits;
/**
* 块的字节数。
*/
unsigned long i_blksize;
/**
* 版本号,每次使用后递增。
*/
unsigned long i_version;
/**
* 文件的块数。
*/
unsigned long i_blocks;
/**
* 文件最后一个块的字节数。
*/
unsigned short i_bytes;
/**
* 非0表示文件是一个套接字。
*/
unsigned char i_sock;
/**
* 保护索引节点某些字段的自旋锁。
*/
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
/**
* 保护索引节点的信号量。
*/
struct semaphore i_sem;
/**
* 在直接IO文件操作中避免出现竞争条件的读写信号量。
*/
struct rw_semaphore i_alloc_sem;
/**
* 索引节点的操作。
*/
struct inode_operations *i_op;
/**
* 缺省文件操作。
*/
struct file_operations *i_fop; /* former ->i_op->default_file_ops */
/**
* inode所在的超级块。
*/
struct super_block *i_sb;
/**
* 文件锁链表,通过此字段将文件上的所有锁链接成一个单链表。
*/
struct file_lock *i_flock;
/**
* 指向address_space对象的指针。
*/
struct address_space *i_mapping;
/**
* 文件的address_space对象。
*/
struct address_space i_data;
#ifdef CONFIG_QUOTA
/**
* 索引节点的磁盘限额。
*/
struct dquot *i_dquot[MAXQUOTAS];
#endif
/* These three should probably be a union */
/**
* 用于具体的字符或块设备的索引节点链表指针。
*/
struct list_head i_devices;
/**
* 如果内核是一个管道则非0
*/
struct pipe_inode_info *i_pipe;
/**
* 指向块设备驱动程序的指针。
*/
struct block_device *i_bdev;
/**
* 表示字符设备的内部数据结构。当inode指向一个字符设备文件时,该字段包含了指向struct cdev结构的指针。
*/
struct cdev *i_cdev;
/**
* 次设备号索引。
*/
int i_cindex;
/**
* 索引节点版本号。由某些文件系统使用。
*/
__u32 i_generation;
#ifdef CONFIG_DNOTIFY
/**
* 目录通知事件掩码。
*/
unsigned long i_dnotify_mask; /* Directory notify events */
/**
* 用于目录通知。
*/
struct dnotify_struct *i_dnotify; /* for directory notifications */
#endif
/**
* 索引节点状态标志。
*/
unsigned long i_state;
/**
* 索引节点弄脏的时间,以jiffies为单位。
*/
unsigned long dirtied_when; /* jiffies of first dirtying */
/**
* 文件系统的安装标志。
*/
unsigned int i_flags;
/**
* 用于写进程的引用计数。
*/
atomic_t i_writecount;
/**
* 索引节点安全结构。
*/
void *i_security;
/**
* 文件系统私有数据指针。
*/
union {
void *generic_ip;
} u;
#ifdef __NEED_I_SIZE_ORDERED
/**
* SMP系统为i_size字段获取一致性时使用的顺序计数器。
*/
seqcount_t i_size_seqcount;
#endif
};
dentry object
/**
* 内核用该结构在内部表示一个文件。它与file不同。file表示的的文件描述符。
* 对单个文件,可能会有许多个表示打开的文件描述符的filep结构,但是它们都指向单个inode结构。
*/
struct inode {
/**
* 通过此字段将对象放入哈希表。
*/
struct hlist_node i_hash;
/**
* 通过此字段将队列链入不同状态的链表中。
*/
struct list_head i_list;
/**
* 通过此字段将其链入到超级块的inode链表中。
*/
struct list_head i_sb_list;
/**
* 引用索引节点的目录项对象链表头。
*/
struct list_head i_dentry;
/**
* 索引节点编号。
*/
unsigned long i_ino;
/**
* 引用计数器。
*/
atomic_t i_count;
/**
* 文件类型与访问权限。
*/
umode_t i_mode;
/**
* 硬链接数目。
*/
unsigned int i_nlink;
/**
* 所有者ID
*/
uid_t i_uid;
/**
* 所有者组标识符。
*/
gid_t i_gid;
/**
* 对表示设备文件的inode结构,该字段包含了真正的设备编号。
*/
dev_t i_rdev;
/**
* 文件的字节数。
*/
loff_t i_size;
/**
* 上次访问文件的时间。
*/
struct timespec i_atime;
/**
* 上次与文件的时间。
*/
struct timespec i_mtime;
/**
* 上次修改索引节点的时间。
*/
struct timespec i_ctime;
/**
* 块的位数。
*/
unsigned int i_blkbits;
/**
* 块的字节数。
*/
unsigned long i_blksize;
/**
* 版本号,每次使用后递增。
*/
unsigned long i_version;
/**
* 文件的块数。
*/
unsigned long i_blocks;
/**
* 文件最后一个块的字节数。
*/
unsigned short i_bytes;
/**
* 非0表示文件是一个套接字。
*/
unsigned char i_sock;
/**
* 保护索引节点某些字段的自旋锁。
*/
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
/**
* 保护索引节点的信号量。
*/
struct semaphore i_sem;
/**
* 在直接IO文件操作中避免出现竞争条件的读写信号量。
*/
struct rw_semaphore i_alloc_sem;
/**
* 索引节点的操作。
*/
struct inode_operations *i_op;
/**
* 缺省文件操作。
*/
struct file_operations *i_fop; /* former ->i_op->default_file_ops */
/**
* inode所在的超级块。
*/
struct super_block *i_sb;
/**
* 文件锁链表,通过此字段将文件上的所有锁链接成一个单链表。
*/
struct file_lock *i_flock;
/**
* 指向address_space对象的指针。
*/
struct address_space *i_mapping;
/**
* 文件的address_space对象。
*/
struct address_space i_data;
#ifdef CONFIG_QUOTA
/**
* 索引节点的磁盘限额。
*/
struct dquot *i_dquot[MAXQUOTAS];
#endif
/* These three should probably be a union */
/**
* 用于具体的字符或块设备的索引节点链表指针。
*/
struct list_head i_devices;
/**
* 如果内核是一个管道则非0
*/
struct pipe_inode_info *i_pipe;
/**
* 指向块设备驱动程序的指针。
*/
struct block_device *i_bdev;
/**
* 表示字符设备的内部数据结构。当inode指向一个字符设备文件时,该字段包含了指向struct cdev结构的指针。
*/
struct cdev *i_cdev;
/**
* 次设备号索引。
*/
int i_cindex;
/**
* 索引节点版本号。由某些文件系统使用。
*/
__u32 i_generation;
#ifdef CONFIG_DNOTIFY
/**
* 目录通知事件掩码。
*/
unsigned long i_dnotify_mask; /* Directory notify events */
/**
* 用于目录通知。
*/
struct dnotify_struct *i_dnotify; /* for directory notifications */
#endif
/**
* 索引节点状态标志。
*/
unsigned long i_state;
/**
* 索引节点弄脏的时间,以jiffies为单位。
*/
unsigned long dirtied_when; /* jiffies of first dirtying */
/**
* 文件系统的安装标志。
*/
unsigned int i_flags;
/**
* 用于写进程的引用计数。
*/
atomic_t i_writecount;
/**
* 索引节点安全结构。
*/
void *i_security;
/**
* 文件系统私有数据指针。
*/
union {
void *generic_ip;
} u;
#ifdef __NEED_I_SIZE_ORDERED
/**
* SMP系统为i_size字段获取一致性时使用的顺序计数器。
*/
seqcount_t i_size_seqcount;
#endif
};
file object
linux/fs.h
/**
* 代表一个打开的文件。由内核在open时创建。当文件的所有实例都被关闭后,才释放该结构。
*/
struct file {
/**
* 用于通用文件对象链表的指针。
*/
struct list_head f_list;
/**
* 文件对应的目录项结构。除了用filp->f_dentry->d_inode的方式来访问索引节点结构之外,设备驱动程序的开发者们一般无需关心dentry结构。
*/
struct dentry *f_dentry;
/**
* 含有该文件的已经安装的文件系统。
*/
struct vfsmount *f_vfsmnt;
/**
* 与文件相关的操作。内核在执行open操作时,对这个指针赋值,以后需要处理这些操作时就读取这个指针。
* 不能为了方便而保存起来。也就是说,可以在任何需要的时候修改文件的关联操作。即"方法重载"。
*/
struct file_operations *f_op;
/**
* 文件对象的引用计数。
* 指引用文件对象的进程数。内核也可能增加此计数。
*/
atomic_t f_count;
/**
* 文件标志。如O_RONLY、O_NONBLOCK和O_SYNC。为了检查用户请求是否非阻塞式的操作,驱动程序需要检查O_NONBLOCK标志,其他标志较少用到。
* 检查读写权限应该查看f_mode而不是f_flags。
*/
unsigned int f_flags;
/**
* 文件模式。FMODE_READ和FMODE_WRITE分别表示读写权限。
*/
mode_t f_mode;
/**
* 网络写操作的错误码。
*/
int f_error;
/**
* 当前的读写位置。它是一个64位数。如果驱动程序需要知道文件中的当前位置,可以读取这个值但是不要去修改它。
* read/write会使用它们接收到的最后那个指针参数来更新这一位置。
*/
loff_t f_pos;
/**
* 通过信号进行邋IO进程通知的数据。
*/
struct fown_struct f_owner;
/**
* 用户的UID和GID.
*/
unsigned int f_uid, f_gid;
/**
* 文件的预读状态。
*/
struct file_ra_state f_ra;
/**
* 一次操作能读写的最大字节数。当前设置为2^31-1
*/
size_t f_maxcount;
/**
* 版本号,每次使用后递增。
*/
unsigned long f_version;
/**
* 文件对象的安全结构指针。
*/
void *f_security;
/* needed for tty driver, and maybe others */
/**
* open系统调用在调用驱动程序的open方法前将这个指针置为NULL。驱动程序可以将这个字段用于任何目的或者忽略这个字段。
* 驱动程序可以用这个字段指向已分配的数据,但是一定要在内核销毁file结构前在release方法中释放内存。
* 它是跨系统调用时保存状态的非常有用的资源。
*/
void *private_data;
#ifdef CONFIG_EPOLL
/* Used by fs/eventpoll.c to link all the hooks to this file */
/**
* 文件的事件轮询等待者链表头。
*/
struct list_head f_ep_links;
/**
* 保护f_ep_links的自旋锁。
*/
spinlock_t f_ep_lock;
#endif /* #ifdef CONFIG_EPOLL */
/**
* 指向文件地址空间的对象。
*/
struct address_space *f_mapping;
};
files_struct
/*
* Open file table structure
*/
/**
* 进程当前打开的文件。
*/
struct files_struct {
/**
* 共享该表的进程数目。
*/
atomic_t count;
/**
* 保护该表的读写自旋锁。
*/
spinlock_t file_lock; /* Protects all the below members. Nests inside tsk->alloc_lock */
/**
* 文件对象的当前最大编号。
*/
int max_fds;
/**
* 文件描述符的当前最大编号。
*/
int max_fdset;
/**
* 上次分配的最大文件描述符加1.
*/
int next_fd;
/**
* 本进程文件对象数组指针。
*/
struct file ** fd; /* current fd array */
/**
* exec时需要关闭的文件描述符指针。
*/
fd_set *close_on_exec;
/**
* 打开文件描述符的指针。
*/
fd_set *open_fds;
/**
* 执行exec时需要关闭的文件描述符的初始集合。
*/
fd_set close_on_exec_init;
/**
* 文件描述符的初始集合。
*/
fd_set open_fds_init;
/**
* 文件对象指针的初始化数组。
*/
struct file * fd_array[NR_OPEN_DEFAULT];
};
参考
- 原文作者:winsun
- 原文链接:https://winsun.github.io/fightsec/post/linux_14_filesystem/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。