0%

《操作系统》Linux 之文件系统

Linux 中,一切都是文件,设备比如网卡、磁盘也被看作文件,对网卡的读写就是对文件的读写

实现这种机制离不开 Linux 提供的一个文件系统的接口层,接口层定义了一系列的方法,比如 open、read、write 等等

Linux 中的用户进程只需要调用接口定义的方法即可对各种设备进行类似于文件的各种操作,只需要这些文件系统实现了接口层

实现层是各种文件系统,包括真实文件系统以及虚拟文件系统

比如:sysfs、proc、cgroup 等等虚拟文件系统以及 ext3、ext4 等等真实的文件系统

cat /proc/filesystems 可以查看当前已经安装的所有文件系统

mount 可以查看所有已经挂载的文件系统的实例(一种文件系统可以有多个实例,比如挂载两个 ext4 的硬盘)

文件系统

每一个文件系统需要通过 mount 系统调用进行挂载安装,必须指定挂载点

比如挂载一个硬盘 mount /dev/sdb /mnt/disks/svn,不指定文件系统类型的话,Linux 默认会选择 ext4,Linux 中自带有 ext4 驱动,实现了文件系统接口中的 read、write 等方法,可以直接驱动硬盘

VFS 虚拟文件系统

在 VFS 框架下编写一个文件系统是十分方便的,只需要实现 VFS 需要用到的接口即可,大量磁盘文件系统被加入了进来。

除此之外,很多“虚拟”的文件系统也被创造出来,为内核提供了很多重要特性

接口层定义的主要内容

每一个文件系统驱动都要实现接口层定义的方法,这样才能被 Linux 所接受

下面看文件系统接口层定义了哪些主要的方法

file_system_type

struct file_system_type 用于描述一个文件系统类,是最先需要定义的结构,其中最重要的是实现 mount 接口。

  • mount() , 挂载一个该类型文件系统实例时被调用,创建 super_block 以及根目录 dentry,并初始化。

例如 cgroup 文件系统实现的 mount 方法中,mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset 就做了一个事情:建立 /sys/fs/cgroup/cpuset 目录下面的所有文件(cpuset.cpus、tasks 等等)

super_operations

管理文件系统整体信息的接口,主要功能是对 inode 资源的管理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct super_operations {
struct inode *(*alloc_inode) (struct super_block *sb);
void (*destroy_inode) (struct inode *);
void (*read_inode) (struct inode *);
void (*dirty_inode) (struct inode *);
void (*write_inode) (struct inode *, int);
void (*put_inode) (struct 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 *, int);
void (*write_super_lockfs) (struct super_block *);
void (*unlockfs) (struct super_block *);
int (*statfs) (struct super_block *, struct statfs *);
int (*remount_fs) (struct super_block *, int *, char *);
void (*clear_inode) (struct inode *);
void (*umount_begin) (struct super_block *);
int (*show_options) (struct seq_file *, struct vfsmount *);
};

dentry_operations

由于会经常的执行目录相关的操作,比如切换到某个目录、路径名的查找等等,为了提高这个过程的效率,引入了目录项的概念

1
2
3
4
5
6
7
8
struct dentry_operations {
int (*d_revalidate) (struct dentry *, int);
int (*d_hash) (struct dentry *, struct qstr *);
int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
int (*d_delete) (struct dentry *);
void (*d_release) (struct dentry *);
void (*d_iput) (struct dentry *, struct inode *);
};

inode_operations

管理 inode 之间关系的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct inode_operations {
int (*create) (struct inode *, struct dentry *,int);
struct dentry * (*lookup) (struct inode *, struct dentry *);
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 *);
int (*readlink) (struct dentry *, char *, int);
int (*follow_link) (struct dentry *, struct nameidata *);
int (*put_link) (struct dentry *, struct nameidata *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *, size_t, int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
};

file_operations

对一个打开的文件进行操作的接口,大部分接口会封装成系统调用提供给应用层使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, char *, size_t, loff_t);
ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
ssize_t (*aio_write) (struct kiocb *, const char *, size_t, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int);
int (*aio_fsync) (struct kiocb *, int);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*readv) (struct file *, const struct iovec *,
unsigned long, loff_t *);
ssize_t (*writev) (struct file *, const struct iovec *,
unsigned long, loff_t *);
ssize_t (*sendfile) (struct file *, loff_t *, size_t,
read_actor_t, void *);
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 flags);
int (*dir_notify) (struct file *filp, unsigned long arg);
int (*flock) (struct file *filp, int cmd, struct file_lock *fl);
};



微信关注我,及时接收最新技术文章