zoukankan      html  css  js  c++  java
  • kernel笔记——VFS

    vfs(the virtual filesystem, virtual file switch)为应用程序访问文件提供了统一的接口,如read、write、open等。

    下面我们看加载文件系统模块、格式化磁盘、挂载磁盘,这些步骤相应的内核实现,vfs在其中又发挥了哪些作用。

    文件系统在内核中由file_system_type结构表示,当我们执行以下命令加载文件系统模块时:

    modprobe ext2

    内核使用了以下函数完成ext2模块注册:

    调用module_init(init_ext2_fs),初始化模块;

    init_ext2_fs函数中,调用register_filesystem注册一个文件系统,register_filesystem将传入的ext2_fs_type加入到一个文件系统链表中,全局变量file_systems为文件系统链表的头结点。

     

    接着我们格式化磁盘:

    mkfs.ext2 /dev/sda5

    以上命令将磁盘的格式设置为ext2文件系统的格式,使得磁盘分区的格式按照指定文件系统的格式定义,如设定块大小、数据块是否连续存放等。

     

    格式化之后,进行磁盘挂载:

    mount /dev/sda5 /mn

    mount命令使用了mount系统调用,在中,可以看到mount系统调用的定义SYSCALL_DEFINE5(mount, …),该函数中,调用do_mount完成实质的挂载工作。

    do_mount首先调用kern_path获取挂载点相关信息,kern_path调用do_path_lookup,通过一系列函数调用,挂载点信息最终被记录在nameidata类型的变量中,nameidata包含挂载点的dentry和vfsmount

     

    接着调用do_new_mount,其用以将ext2文件系统安装到/mnt,do_new_mount调用do_kern_mount,do_kern_mount调用vfs_kern_mount,vfs_kern_mount通过调用alloc_vfsmnt新建一个vfsmount,vfs_kern_mount再调用type->get_sb,这里type为之前加载ext2模块时注册的ext2_fs_type,get_sb对应于ext2_fs_type中的ext2_get_sb

     

    ext2_get_sb调用get_sb_bdev,get_sb_bdev中调用sget新建一个super_block,之后调用ext2_fill_super,ext2_fill_super中调用ext2_iget新建一个inode,该inode作为挂载点的虚拟根,之后调用d_alloc_root新建一个dentry

    回到do_new_mount函数,do_kern_mount返回后将调用do_add_mount,do_add_mount调用graft_tree将之前新建的vfsmount添加到一个hash表中

    以上是挂载的底层实现过程,过程中创建了vfsmount、super_block、inode和dentry结构类型的变量,通过结构内部指针字段将各结构与其他结构关联,将super_block、inode等结构的操作函数设置为与新文件系统对应的操作函数(如ext2_sops、ext2_dir_inode_operations),并使用新建的vfsmount、dentry、inode替换原来/mnt的相应结构。

    所有挂载点,都有一个虚拟的、隐藏的根,挂载完成之后,操作挂载点中的目录或文件,将使用新注册的方法,如/dev/sda5挂载上/mnt之后,/mnt下的目录与文件将使用ext2提供的super_operations、inode_operations、file_operations等方法;而在挂载之前,/mnt使用的是”/”挂载点提供的方法。

    使用crash解析vmcore文件,执行mount命令可以看到系统的挂载项:

    crash> mount
            VFSMOUNT         SUPERBLK   TYPE    DEVNAME DIRNAME
    ffff8806281ccd80 ffff8806281ca400 rootfs     rootfs /
    ffff880629f895c0 ffff880631d83400 tmpfs        udev /dev
    ffff880629f893c0 ffff8806319b1400 devpts     devpts /dev/pts
    ffff8806281cc180 ffff880633d8a400 ext3    /dev/sda2 /
    ffff8806281cc680 ffff880628785800 proc         proc /proc
    ffff880636be9ec0 ffff8806281ca800 sysfs       sysfs /sys
    ffff880629f896c0 ffff880628dc2400 debugfs   debugfs /sys/kernel/debug
    ffff880636be95c0 ffff880633586400 binfmt_misc  none /proc/sys/fs/binfmt_misc
    ffff880629f894c0 ffff8806351b1400 tmpfs       tmpfs /dev/shm
    ffff880636be92c0 ffff88062fba5400 ext2    /dev/sda5 /mnt

    每一个挂载点对应一个vfsmount结构,以上输出中最左一列就是挂载点vfsmount结构对应的地址。

     

    再执行struct vfsmount <vfsmount< span="">的地址>,我们就可以将vfsmount结构的内容解析出来:

    struct vfsmount {
        ……
        mnt_parent = 0xffff8806281cc180,
        mnt_mountpoint = 0xffff88061572ebc0,
        mnt_root = 0xffff88051e2bd240,
        ……
        mnt_devname = 0xffff880634fe2460 "/dev/sda5",
    };

    对于vfsmount结构,我们主要看以上几个字段:

    • mnt_parent: 上一层挂载点的vfsmount结构(这里为”/”对应的vfsmount)
    • mnt_mountpoint: 其为挂载点对应的dentry(这里为mnt对应的dentry)
    • mnt_root: 上一层挂载点对应的dentry(这里为”/”对应的dentry)
    • mnt_devname: 指示挂载设备名称(这里为/dev/sda5)

    在进行挂载之前,执行stat /mnt命令可以看到,可以看到/mnt与一个inode对应:

    linux # stat /mnt
      File: `/mnt'
      Size: 4096     Blocks: 8     IO Block: 4096 directory
    Device: 802h/2050d     Inode: 1970417     Links: 2

    在挂载之后,inode变成另一个数值:

    linux # stat /mnt
      File: `/mnt'
      Size: 4096     Blocks: 8     IO Block: 4096 directory
    Device: 805h/2053d     Inode: 2     Links: 3

    新的inode不再是磁盘上的一个项,而存在于内存中(即以上mount步骤中建立的虚拟根),并且对应于挂载点上新的文件系统。

     

    我们可以通过解析挂载点的vfsmount,再解析挂载点的dentry结构,即mnt_root,再解析相应的inode结构,即d_inode,就可找到挂载点相应的inode结构,查看到i_ino字段的值。

     

    总的而言,使用mount挂载文件系统,其主要完成以下两项工作:

    • 创建一个vfsmount
    • 新建一个虚拟根,替换原来的inode

     

    Reference: Chapter 13 - The Virtual Filesystem, Linux kernel development.3rd.Edition

  • 相关阅读:
    ubuntu安装ActiveMQ
    UTF-8和GBK区别
    MapReduce实现二次排序(温度年份排序)
    MapReduce实现倒排索引
    MapReduce实现多表链接
    MapReduce实现单表链接
    Linux服务器的性能调优实战篇CentOS6最小化安装后的优化
    Linux服务器的性能调优理论篇
    Windows中安装bash Cygwin工具
    shell基础知识
  • 原文地址:https://www.cnblogs.com/felixzh/p/9047645.html
Copyright © 2011-2022 走看看