Linux内核设计与实现 总结笔记(第十三章)虚拟文件系统

一、通用文件系统接口

Linux通过虚拟文件系统,使得用户可以直接使用open()、read()、write()访问文件系统,这种协作性和泛型存取成为可能。

不管文件系统是什么,也不管文件系统位于何种介质,采用策略是统一的。

二、文件系统抽象层

为了支持多文件系统,VFS提供了一个通用文件系统模型, 囊括了任何文件系统的常用功能集和行为。

用户空间的write()将调用VFS的sys_write(),然后调用文件系统中文件系统的写方法,最后写进物理介质中去。

 

三、Unix文件系统

Unix使用了四种和文件系统相关的传统抽象概念:文件、目录项、索引节点、安装点。

从本质上讲文件系统是特殊的数据分层存储结构,它包括文件、目录和相关的控制信息。

文件系统的通用操作包含创建、删除和安装等。多有已安装的文件系统都作为根文件系统树的枝叶出现在系统中。 

文件其实可以做一个有序字节串,字节串抵押给字节是文件的头,最后一个字节是文件的尾。

文件通过目录组织起来,文件目录好比一个文件夹,用来容纳相关文件。目录可以包含子目录,层层嵌套,形成文件路径。

Unix系统将文件的相关信息和文件本身这两个概念加以区分,例如访问控制权限、大小、拥有者、创建按时间等信息。

而文件相关的信息被存储在单独的结构中,被称作索引节点。

 

四、VFS对象及其数据结构

VFS有四个主要对象类型,分别是:

  • 超级块对象:代表一个具体的已安装文件系统。
  • 索引节点对象:代表一个具体文件
  • 目录项对象:代表一个目录项,是路径的要给组成部分
  • 文件对象:代表由进程打开的文件

每个对象都有对应的操作对象:

super_operations对象:其中包括内核针对特定文件系统所能调用的方法

inode_operations对象:其中包括内核针对特定文件所能调用的方法

dentry_operations对象:其中包括内核针对特定目录所能调用的方法

file_operations对象:其中包括进程对已打开文件所能调用的方法

如果通用函数提供的基本功能无法满足需求,那么就必须使用实际文件系统的独有方法填充这些函数指针,使其指向文件系统实例。这里的对象是结构体指针,不是类。 

五、超级块对象

定义在文件<linux/fs.h>中,创建、管理撤销超级块对象的代码位于文件fs/super.c中。

struct super_block {
    struct list_head s_list;    /* 指向所有超级块的链表 */
    dev_t s_dev;        /* 设备标识符 */
    unsigned long s_blocksize;    /* 以字节为单位的块大小 */
    unsigned char s_blocksize_bits;    /* 以位为单位的块大小 */
    unsigned char s_dirt;        /* 修改(脏)标志 */
    unsigned long long s_maxbytes;    /* 文件大小上限 */
    struct file_system_type s_type;    /* 文件按系统类型 */
    struct super_operations s_op;    /* 超级块方法 */
    struct quotactl_operations *dp_op;    /* 磁盘限额方法 */
    struct export_operations *s_export_op;    /* 导出方法 */
    unsigned long s_flags;        /* 挂载文件标志 */
    struct dentry *s_root;        /* 目录挂载点 */
    struct rw_semaphore s_umount;    /* 卸载信号量 */
    struct semaphore s_lock;        /* 超级块信号量  */
    int s_count;                    /* 超级块引用计数 */
    int s_need_sync;            /* 尚未同步标志 */
    atomic_t s_active;        /* 活动引用计数 */
    void *s_security;            /* 安全模块 */
    struct xattr_handler **s_xattr;        /* 扩展的属性操作 */
    struct list_head s_inodes;        /* inodes链表 */
    struct list_head s_dirty;            /* 脏数据链表 */
    struct list_head s_io;                /* 回写链表 */
    struct list_head s_more_io;        /* 更多回写的链表 */
    struct hlist_head s_anon;            /* 匿名目录项 */
    struct list_head s_files;            /* 被分配文件链表 */
    struct list_head s_dentry_lru;    /* 未被使用目录项链表 */
    int s_nr_dentry_unused;        /* 链表中目录项的数目 */
    struct block_device *s_bdev;    /* 相关的块设备 */
    struct mtd_info *s_mtd;        /* 存储磁盘信息 */
    struct list_head s_instances;    /* 该类型文件系统 */
    struct quota_info    s_dquot;    /* 限额相关选项 */
    int s_frozen;                /* frozen标志位 */
    wait_queue_head_t s_wait_unfrozen;    /* 冻结的等待队列 */
    char s_id[32];            /* 文本名字 */
    void *s_fs_info;        /* 文件系统特殊信息 */
    fmode_t s_mode;        /* 安装权限 */
    struct semaphore s_vfs_rename_sem;    /* 重命名信号量 */
    u32 s_time_gran;        /* 时间戳粒度 */
    char *s_subtype;        /* 子类型名称 */
    char *s_options;        /* 已存安装选项 */
};
super_block结构

 

六、超级块操作

超级块最重要的一个域是s_op,指向超级块的操作函数表。super_operations结构体表示,定义文件<linux/fs.h>:

struct super_operations {
    struct inode *(*alloc_inode)(struct super_block *sb);
    void (*destroy_inode)(struct inode *);
    void (*dirty_inode)(struct inode *);
    int (*write_inode)(struct inode *, int);
    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);
    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 (*clear_inode)(struct inode *);
    void (*umount_begin)(struct super_block *);
    int (*show_options)(struct seq_file *, struct vfsmount *);
    int (*show_stats)(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);
    int (*bdev_try_to_free_page)(struct super_block *, struct page*, gfp_t);
};
super_operations

当文件需要对其超级块执行操作时,首先要寻找需要的操作方法:

struct inode *alloc_inode(struct super_block *sb)
在给定超级块下创建和初始化一个新的索引节点

void destroy_inode(struct inode *inode)
VFS在索引节点脏时会调用此函数。日志文件系统执行该函数更新日志

void write_inode(struct inode *inode, int wait)
用于将给定的索引节点写入磁盘,wait参数指明写操作是否需要同步

void drop_inode(struct inode *inode)
在最后一个指向索引节点的引用被释放后,VFS会调用该函数。

void delete_inode(struct inode *inode)
用于从磁盘上删除给定的索引节点

void put_super(struct super_block *sb)
在卸载文件系统时由VFS调用,用来释放超级块。必须一直持有s_lock锁

void write_super(struct super_block *sb)
用给定的超级块更新磁盘上的超级块。

int sync_fs(struct super_block *sb, int wait)
使文件系统的数据元与磁盘上的文件系统同步。

void write_super_lockfs(struct super_block *sb)
首先禁止对文件系统做该表,再使用给定的超级块更新磁盘上的超级块

void unlockfs(struct super_block *sb)
对文件系统解除锁定,write_super_lockfs()逆操作

int statfs(struct super_block *sb, struct statfs *statfs)
VFS通过调用该函数获取文件系统状态。

int remount_fs(struct super_block *sb, int *flags, char *data)
当指定新的安装选项重新安装我呢见系统时,VFS会调用该函数。

void clear_inode(struct inode *inode)
VFS调用该函数释放索引节点,并清空包含相关数据的所有页面

void umount_begin(struct super_block *sb)
VFS调用该函数中断安装操作。
超级块方法

 

七、索引节点对象

struct inode {
    struct hlist_node i_hash;        /* 散列表 */
    struct list_head i_list;            /* 索引节点链表 */
    struct list_head i_sb_list;        /* 超级块链表 */
    struct list_head i_dentry;        /* 目录项链表 */
    unsigned long i_ino;                /* 节点号 */
    atomic_t    i_count;                /* 引用计数 */
    unsigned int i_nlink;                /* 硬链接数 */
    uid_t i_uid;                            /* 使用者的id */
    gid_t i_gid;                            /* 使用组的id */
    kdev_t i_rdev;                        /* 实际设备标识符 */
    u64 i_version;                        /* 版本号 */
    loff_t i_size;                            /* 以字节为单位的文件大小 */
    seqcount_t i_size_seqcount;    /* 对i_size进行串行计数 */
    struct timespec i_atime;            /* 最后访问时间 */
    struct timespec i_mtime;            /* 最后修改时间 */
    struct timespec i_ctime;            /* 最后改变时间 */
    unsigned int i_blkbits;                /* 以位为单位的块大小 */
    blkcnt_t i_blocks;                    /* 文件的块数 */
    unsgined short i_bytes;            /* 使用的字节数 */
    umode_t i_mode;                    /* 访问权限 */
    spinlock_t i_lock;                    /* 自旋锁 */
    struct rw_semaphore i_alloc_sem;    /* 嵌入i_sem内部 */
    struct semaphore i_sem;                /* 索引节点信号量 */
    struct inode_operations *i_op;            /* 索引节点操作表 */
    struct file_operations *i_fop;                /* 缺省的索引节点操作 */
    struct super_block *i_sb;                /* 相关的超级块 */
    struct file_lock *i_flock;                    /* 文件锁链表 */
    struct address_space *i_mapping;        /* 相关的地址映射 */
    struct address_space i_data;                /* 设备地址映射 */
    struct dquot *i_dquot[MAXQUOTAS];    /* 索引节点的磁盘限额 */
    struct list_head i_devices;                /* 块设备链表 */
    union {
        struct pipe_inode_info *i_pipe;        /* 管道信息 */
        struct block_device *i_bdev;            /* 块设备驱动 */
        struct cdev *i_cdev;                        /* 字符设备驱动 */
    };
    unsigned long i_dnotify_mask;            /* 目录通知掩码 */
    struct dnotify_struct *i_dnotify;            /* 目录通知 */
    struct list_head inotify_watched;            /* 索引节点通知监测链表*/
    struct mutex inotify_mutex;            /* 保护inotify_watches */
    unsigned long i_state;                        /* 状态标志 */
    unsigned long dirtied_when;                /* 第一次弄脏数据的时间 */
    unsigned int i_flags;                        /* 文件系统标志 */
    atomic_t i_writecount;                    /* 写者计数 */
    void *i_security;                            /* 安全模块 */
    void *i_private;                                /* fs私有指针 */
};
struct inode

 一个索引节点代表文件系统中的一个文件,它也可以是设备或管道这样的特殊文件。

 

八、索引节点操作

 

九、目录项对象

 

十、目录项操作

 

十一、文件对象

 

十二、文件操作

 

十三、文件系统相关的数据结构

 

十四、和进程相关的数据结构

转载于:https://www.cnblogs.com/ch122633/p/11402862.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值