一、结构体种类:
1、超级块对象struct super_block *sb:
超级块代表了整个文件系统,超级块是文件系统的控制块,有整个文件系统信息,一个文件系统所有的inode
都要连接到超级块上,可以说,一个超级块就代表了一个文件系统。每次一个实际的文件系统被安装时,内核会从
磁盘的特定位置读取一些控制信息来填充内存中的超级块对象。super_block定义在include/linux/fs.h里:
struct super_block {
struct list_head s_list; /*指向超级块链表的指针*/
unsigned char s_blocksize_bits; /*文件系统的块大小的位数*/
unsigned long s_blocksize; /*文件系统的块大小*/
loff_t s_maxbytes; /* 最大文件大小 */
struct file_system_type *s_type; /*文件系统类型*/
const struct super_operations *s_op; /*super_block的操作函数集合*/
const struct dquot_operations *dq_op; /*文件系统的限额操作函数集合*/
unsigned long s_flags; /*文件系统的超级块的状态位*/
struct dentry *s_root; /*指向根目录的dentry结构体*/
int s_count; /*引用计数*/
char s_id[32]; /* 文件系统的名字 */
void *s_fs_info; /* 文件系统的私有信息指针 */
struct list_head s_inodes; /* 文件系统的inode结构体都在这个队列上 */
//......
};
super block操作函数接口:
struct super_operations {
struct inode *(*alloc_inode)(struct super_block *sb);
void (*destroy_inode)(struct inode *);
void (*dirty_inode) (struct inode *, int flags);
int (*write_inode) (struct inode *, struct writeback_control *wbc);
#ifdef CONFIG_QUOTA
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);
struct dquot **(*get_dquots)(struct inode *);
#endif
//......
}
2、索引节点对象struct inode * inode:
索引节点对象存储了文件的相关信息,代表了存储设备上的一个实际的物理文件。当一个 文件首次被访问时,
内核会在内存中组装相应的索引节点对象,以便向内核提供对一个文件进行操 作时所必需的全部信息;这些信息
一部分存储在磁盘特定位置,另外一部分是在加载时动态填充的。
struct inode {
umode_t i_mode; /*访问权限控制*/
kuid_t i_uid; /*使用者id*/
kgid_t i_gid; /*使用者id组*/
unsigned int i_flags; /*文件系统标志*/
const struct inode_operations *i_op; /*inode 操作接口*/
struct super_block *i_sb; /*相关的超级块*/
/* Stat data, not accessed from path walking */
unsigned long i_ino; /*节点号*/
loff_t i_size; /*以字节为单位的文件大小*/
struct timespec i_atime; /*最后访问时间*/
struct timespec i_mtime; /*最后修改(modify)时间*/
struct timespec i_ctime; /*最后改变(change)时间*/
unsigned long dirtied_when; /* 首次修改时间 */
spinlock_t i_lock; /*文件的块数*/
unsigned long i_state; /*状态标志*/
u64 i_version; /*版本号*/
atomic_t i_count; /*引用记数*/
atomic_t i_dio_count;
atomic_t i_writecount; /*写者记数*/
const struct file_operations *i_fop; /* 索引节点操作 */
};
3、文件对象struct file *file:
struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件
在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。
在文件的所有实例都关闭后,内核释放这个数据结构。一个文件对应的文件对象可能不是惟一的,但是其对应的
索引节点和 目录项对象无疑是惟一的。在内核创建和驱动源码中,struct file的指针通常被命名为file或filp。
struct file {
struct path f_path; /* 包含dentry和mnt两个成员,用于确定文件路径 */
const struct file_operations *f_op; /* 与该文件相关联的操作函数 */
atomic_long_t f_count; /* 文件的引用计数(有多少进程打开该文件) */
unsigned int f_flags; /* 这些是文件标志, 例如 O_RDONLY, O_NONBLOCK, 和 O_SYNC */
fmode_t f_mode; /* 读写模式:open的mod_t mode参数 */
loff_t f_pos; /* 该文件在当前进程中的文件偏移量 */
struct fown_struct f_owner; /* 该结构的作用是通过信号进行I/O时间通知的数据*/
} __attribute__((aligned(4)));
对应的函数操作接口:
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
//......
}
4、struct dentry 目录项:
//kernel-4.9/include/linux/dcache.h
struct dentry {
unsigned int d_flags; /* 目录项标志 */
struct hlist_bl_node d_hash; /* 散列表表项的指针 */
struct dentry *d_parent; /* 父目录的目录项对象 */
struct qstr d_name; /* 文件名 */
struct inode *d_inode; /* 与文件名关联的索引节点 */
unsigned char d_iname[DNAME_INLINE_LEN]; /* 存放短文件名 */
const struct dentry_operations *d_op; /* 目录项操作方法 */
struct super_block *d_sb; /* 文件的超级块对象 */
void *d_fsdata; /* 与文件系统相关的数据 */
struct list_head d_subdirs; /* 子目录 */
//......
};
对应的函数操作接口:
struct dentry_operations {
int (*d_compare)(const struct dentry *,
unsigned int, const char *, const struct qstr *);
int (*d_delete)(const struct dentry *);
int (*d_init)(struct dentry *);
void (*d_release)(struct dentry *);
void (*d_prune)(struct dentry *);
void (*d_iput)(struct dentry *, struct inode *);
char *(*d_dname)(struct dentry *, char *, int);
struct vfsmount *(*d_automount)(struct path *);
//......
} ____cacheline_aligned;
二、数据结构之间的关系:
在进程中打开一个文件F,实际上就是要在内存中建立的dentry和inode结构,并让它们与进程结构联系来,
把VFS中定义的接口给接起来,可以用如下两图表明:
作者:frank_zyp
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文无所谓版权,欢迎转载。