Linux虚拟文件系统vfs与文件操作始末

        虚拟文件系统(vfs)是Linux内核的子系统,其设计目的是对用户层(系统调用)屏蔽底层(各特定文件系统)实现的复杂性,对底层提供统一的接口与数据结构,使得能衔接各个特定文件系统(如ext2、ext3、fat32等)的对接,是用户层与文件系统层之间的抽象层。

    与vfs层相关的主要数据结构有以下几个:超级块对象super_block、索引节点对象inode、目录项dentry、文件对象file、文件系统类型file_system_type、挂载的文件系统vfsmount等。

       下面简单介绍下从磁盘分区格式化到文件挂载和文件操作的几个过程,与vfs层以及具体文件系统层相对应的工作机制流程,见下表:

命令功能底层流程原理及作用
mkfs.ext3 /dev/sda4  格式化磁盘分区,将文件系统信息写入到磁盘超级块,为以特定的文件系统格式读写做铺垫格式化时的读写磁盘不需要通过文件系统层,即跨过文件系统,直接写入磁盘(通过块设备驱动写入,与dd命令类似)。

strace跟踪dd命令open(/dev/sda4) = 3

read(3),读写块设备/dev/sda4的方式就是跨过文件系统,直接写入磁盘

insmod ext3.ko内核装载ext3驱动模块,向内核注册ext3文件系统。文件系统登记在file_system_type全局链表中提供ext3文件系统各种函数,如填充操作块,索引节点操作函数,如分配ext4_alloc_inode、读写索引节点
mount -t ext3  /dev/sda4  /mnt/abc建立在内核已经注册ext3文件系统的基础之上,挂载sda4分区建立vfs_mount对象,该对象代表挂载的文件系统(挂载点)file_system_type中的方法get_sb调用alloc_super函数填充内存超级块对象(vfs_mount中相关的超级块对象)

    使用Linux文件系统是这样的情景,我们得先分区(如划分/dev/sda4),然后格式化成具体文件系统类型(如ext3),再然后挂载到某个目录(如/mnt),最后在mnt目录及层层子目录下进行相关的文件操作(如打开创建、读写、关闭、删除等)。

1、格式化

进行ext3格式化时会:Writing superblocks and filesystem accounting information,这是执行mkfs.ext3输出的信息,格式化会将特定文件系统控制信息写入到磁盘分区超级块,待mount磁盘分区时被读出,下面介绍mount。

2、挂载mount
      我们知道要使用一个文件系统首先要 mount 才可使用。我们清楚了以上结构后,接着来看 vfs_kern_mount() 函数,这个函数是内核最终实现 mount 的函数,调用关系如下:
   mnt = alloc_vfsmnt(name);                               //建立vfs_mount对象
   type->get_sb(type, flags, name, data, mnt);    //调用文件系统的方法从磁盘超级块中获取超级块
    ext3_fill_super                                               //填充超级块                                                                    sb->s_op = &ext3_sops;                   //超级块操作对象,包括ext3_read_inode()
      sb->s_root = d_alloc_root(root);                  //超级块的根目录项
        struct qstr name = { .name = "/", .len = 1 };
  mnt->mnt_sb = sb;                                          //将超级块关联挂载的文件系统
  mnt->mnt_root = dget(sb->s_root);                 //该文件系统的根目录项对象,就是根目录/
  mnt->mnt_mountpoint = mnt->mnt_root;        //安装点的目录项对象,也即上表挂载的abc目录

3、打开(创建)文件                                                                                                                     

下面是open系统调用在内核中的实现                                                                                                 sys_open:                                                                                                                                       
 do_filp_open                                                                                                                       
  path_walk                                                                                                                                    
   do_lookup
   real_lookup
    ext3_lookup(parent->i_op->lookup)                               //查找inode
     struct inode *iget(parent->i_sb, unsigned long ino)       //获取inode                                                    sb->s_op->read_inode(inode);          //ext3_read_inode() //从磁盘获取子inode填充
 nameidata_to_filp
  __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp)
   f->f_path.dentry = dentry;                                            
   f->f_path.mnt = mnt;
   f->f_op = fops_get(inode->i_fop);                              //将inode的文件操作对象赋给打开的文件对象的操作对象,如ext3_file_operations
   if (!open && f->f_op)                                                //如果open实现不存在
      open = f->f_op->open;
   if (open) 
     error = open(inode, f);                                                                                                                                          

4、打开的文件对象file                                                                                                                   

    用户层read->sys_read->file->read->do_sync_read,do_sync_read为具体文件系统(如ext3)ext3_sops操作对象中read的实现。

5、文件系统注册到内核file_system_type全局链表中                                                                        
module_init(init_ext3_fs) //ext3 文件驱动加载  super.c 提供注册文件系统方法等。
 init_ext3_fs
  register_filesystem(&ext3_fs_type);                       //插入file_system_type全局链表

6、ext3相关数据结构                                                                                                                                

//ext3文件系统类型数据结构,来自ext3.ko 中super.c文件
static struct file_system_type ext3_fs_type = {
    .owner        = THIS_MODULE,
    .name        = "ext3",
    .get_sb        = ext3_get_sb,
    .kill_sb    = kill_block_super,
    .fs_flags    = FS_REQUIRES_DEV,
};
//ext3超级块操作对象,来自ext3.ko 中super.c文件
static struct super_operations ext3_sops = {            
    .alloc_inode    = ext3_alloc_inode,
    .destroy_inode    = ext3_destroy_inode,
    .read_inode    = ext3_read_inode,
    .write_inode    = ext3_write_inode,
    .dirty_inode    = ext3_dirty_inode,
    .delete_inode    = ext3_delete_inode,
    .put_super    = ext3_put_super,
    .write_super    = ext3_write_super,
    .sync_fs    = ext3_sync_fs,
    .write_super_lockfs = ext3_write_super_lockfs,
    .unlockfs    = ext3_unlockfs,
    .statfs        = ext3_statfs,
    .remount_fs    = ext3_remount,
    .clear_inode    = ext3_clear_inode,
    .show_options    = ext3_show_options,
#ifdef CONFIG_QUOTA
    .quota_read    = ext3_quota_read,
    .quota_write    = ext3_quota_write,
#endif
};

//ext3文件操作对象,来自ext3.ko 中super.c文件
const struct file_operations ext3_file_operations = {
    .llseek        = generic_file_llseek,
    .read        = do_sync_read,
    .write        = do_sync_write,
        .aio_read    = generic_file_aio_read,
    .aio_write    = ext3_file_write,
    
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值