二,与进程联系的文件系统相关结构
文件描述符用于在一个进程中唯一标识打开的文件。假定内核能够在用户进程中和内核内部使用的结构之间,建立一种关联。每个进程的task_struct中包含了用于完成该工作的成员。
struct task_struct {
......
//用于查找环形链表时防止无限循环。
int link_count, total_link_count;
......
struct fs_struct *fs;
struct files_struct *files;
struct nsproxy *nsproxy;
......
};
struct fs_struct {
int users;
spinlock_t lock;
seqcount_t seq;
int umask;
int in_exec;
struct path root, pwd;
};
Umask:表示标准的掩码,用于设置新文件的权限。
root、pwd:指定了进程的根目录和当前工作目录。
结构files_struct是用户打开文件描述表,它给出了所有文件描述符的使用情况。
struct files_struct {
atomic_t count;
struct fdtable __rcu *fdt;
struct fdtable fdtab;
spinlock_t file_lock ____cacheline_aligned_in_smp;
int next_fd;
struct embedded_fd_set close_on_exec_init;
struct embedded_fd_set open_fds_init;
struct file __rcu * fd_array[NR_OPEN_DEFAULT];
};
next_fd:下一个文件描述符。
close_on_exec_init;:对执行exec时将关闭的所有文件描述符,在该 位图中对应的比特位都将置为。
open_fds_init:文件描述符集合。
fd_array:存储所有打开文件的file结构。
struct fdtable {
unsigned int max_fds;//进程可以处理的最大文件描述符数目。
struct file __rcu **fd;
fd_set *close_on_exec;
fd_set *open_fds;
struct rcu_head rcu;
struct fdtable *next;
};
Fdtable结构中fd,close_on_exec,open_fds分别指向files_struct 结构中的fd_array,close_on_exec_init,open_fds_init。在files_struct结构中能够处理的描述符是有限的,如果要打开更多的文件,内核会分配更大存储空间的字段,让fdtable中的指针指向新值。
struct file {
union {
struct list_head fu_list;
struct rcu_head fu_rcuhead;
} f_u;
struct path f_path;
#define f_dentry f_path.dentry
#define f_vfsmnt f_path.mnt
const struct file_operations *f_op;
spinlock_t f_lock;
......
atomic_long_t f_count;
unsigned int f_flags;
fmode_t f_mode;
loff_t f_pos;
struct fown_struct f_owner;
......
struct address_space *f_mapping;
.....
};
fu_list:超级块提供了一个s_files成员作表头,以建立file对象的链 表,链表元素是fu_list,该链表包含超级块表示的文件系统的所有打开的文件。
f_op:指向文件操作结构。
f_flags:指定了在open系统调用时传递的额外的标志。
f_mode:文件的打开模式。
f_pos:文件操作指针在文件中的当前位置。
f_owner:包含了处理文件的进程有关的信息(也确定了SIGIO信号 的目标PID,以实现异步输入输出)。
f_mapping:指向所属文件相关inode实例的地址空间映射。
三,系统有关的操作函数集
结构super_operations是对文件系统超级块进行操作的函数集。操作的实现必须由底层文件系统提供。
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);
int (*drop_inode) (struct inode *);
void (*evict_inode) (struct inode *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
int (*sync_fs)(struct super_block *sb, int wait);
int (*freeze_fs) (struct super_block *);
int (*unfreeze_fs) (struct super_block *);
int (*statfs) (struct dentry *, struct kstatfs *);
int (*remount_fs) (struct super_block *, int *, char *);
void (*umount_begin) (struct super_block *);
int (*show_options)(struct seq_file *, struct vfsmount *);
int (*show_devname)(struct seq_file *, struct vfsmount *);
int (*show_path)(struct seq_file *, struct vfsmount *);
int (*show_stats)(struct seq_file *, struct vfsmount *);
......
};
alloc_inode:在给定的超级块下创建并初始化一个新的索引节点。
destroy_inode:释放给定的索引节点。
dirty_inode:索引节点被修改时调用该函数。
write_inode:将指定的索引节点写回磁盘。
drop_inode:在最后一个索引节点被释放后,VFS调用该函数。
put_super:在卸载文件系统时VFS调用,用于释放超级块。
write_super:更新磁盘上的超级块。
sync_fs:使文件系统的数据元素与磁盘上的文件系统同步,wait参数 指定操作是否同步。
Statfs:VFS调用该函数获取文件系统状态,文件系统信息放置在 kstatfs中。
remount_fs:当制定新的安装选项重新安装文件系统时VFS调用该函 数。
umount_begin:仅用于网络文件系统和用户空间文件系统,仅在文件 系统强制卸载时调用该方法。
show_options:用于proc文件系统,用于显示文件系统装载的选项。
show_stats:提供了文件系统的统计信息,同样用于proc文件系统。
结构inode_operations中操作函数主要负责结构性操作,(例如删除一个文件)和文件相关元数据操作(例如属性)。
struct inode_operations {
struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
void * (*follow_link) (struct dentry *, struct nameidata *);
int (*permission) (struct inode *, int);
struct posix_acl * (*get_acl)(struct inode *, int);
int (*readlink) (struct dentry *, char __user *,int);
void (*put_link) (struct dentry *, struct nameidata *, void *);
int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
int (*link) (struct dentry *,struct inode *,struct dentry *);
int (*unlink) (struct inode *,struct dentry *);
int (*symlink) (struct inode *,struct dentry *,const char *);
int (*mkdir) (struct inode *,struct dentry *,int);
int (*rmdir) (struct inode *,struct dentry *);
int (*mknod) (struct inode *,struct dentry *,int,dev_t);
int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
void (*truncate) (struct inode *);
......
void (*truncate_range)(struct inode *, loff_t, loff_t);
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
u64 len);
} ____cacheline_aligned;
Lookup:在父目录中查找指定文件的dentry。
follow_link:通过一个符号链接查找它实际指向的索引节点。
readlink:读符号链接。
Permission:得到节点权限。
Create:创建节点,代表目录的节点才提供这个函数。
Link:用于在指定目录下创建一个硬链接。这个link函数最终会被系 统调用link()调用。该函数的第一个参数是原始文件的dentry,第二个参数为上述指定目录的inode,第三个参数是链接文件的dentry。
Symlink:在某个目录下创建符号链接。
mkdir:在指定目录下创建一个子目录,当前目录的inode会调用 i_op->mkdir()。该函数会被系统调用mkdir()调用。第一个参数即为指定目录的inode,第二个参数为子目录的dentry,第三个参数为子目录权限。
Mknod:在指定的目录下创建一个特殊文件,比如管道、设备文件或 套接字等。
Rename:文件或目录重命名。
Truncate:将文件长度剪短。
truncate_range:用于截断一个范围内的块。
dentry_operations结构保存了一些指向各种特定于文件系统可以对dentry对象执行的操作的函数指针。
struct dentry_operations {
int (*d_revalidate)(struct dentry *, struct nameidata *);
int (*d_hash)(const struct dentry *, const struct inode *,
struct qstr *);
int (*d_compare)(const struct dentry *, const struct inode *,
const struct dentry *, const struct inode *,
unsigned int, const char *, const struct qstr *);
int (*d_delete)(const 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 *);
int (*d_manage)(struct dentry *, bool);
} ____cacheline_aligned;
d_revalidate:对于网络文件系统特别重要。它检查内存中的各个dentry 对象构成的结构是否仍然能够反映当前文件系统中的情况。因为网络文件系统并不直接关联到内核/VFS,所有信息都必须通过网络连接收集,可能由于文件系统在存储端的改变,致使某些dentry不再有效。该函数用于确保一致性。
d_hash:计算散列值,该值用于将对象放置到dentry散列表中。
d_compare:比较两个dentry对象的文件名。尽管VFS只执行简单的 字符串比较,但文件系统可以替换默认实现,以适合自身的需求。
d_delete:在确认dentry对象仍然包含在全局dentry散列表中之后, 使用__d_drop将其移出。如果该对象此时只剩下一个使用者,还会调用dentry_iput将相关inode的使用计数减1。
d_iput:从一个不再使用的dentry对象中释放inode。
各个file实例都包含一个指向struct file_operations实例的指针,该结构保存了所有可能文件操作的函数指针。
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 (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
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 *);
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
long (*fallocate)(struct file *file, int mode, loff_t offset,
loff_t len);
};
Llseek:文件操作指针在文件中定位。
aio_read:用于异步读取操作。
Readdir:读取目录内容,只对目录对象适用。
Poll:用于poll和select系统调用,以便实现同步的I/O多路复用。
Mmap:用来请求将设备内存映射到进程的地址空间。
Flush:操作在进程关闭它的设备文件描述符的拷贝时调用,它应当 执行设备的任何未完成的操作。
Release:在文件结构被释放时调用这个操作。
Fsync:这个方法是fsync系统调用的后端,用户调用来刷新任何挂着 的数据。
Fasync:用于启用/停用有信号控制的输入和输出。
Lock:用于锁定文件,对多个进程的并发文件访问进行同步。
Sendpage:它由内核调用来发送数据,一次一页,到对应的文件。设 备驱动实际上不实现sendpage。
get_unmapped_area:这个方法的目的是在进程的地址空间找一个合适 的位置来映射在底层设备上的内存段,这个任务通常由内存管理代码进行。
check_flags:这个方法允许模块检查传递给fcntl(F_SETFL...)调用的 标志。
splice_write:用于从管道向文件传输数据。