• 烈日融雪
    2019-06-05
    结合《Linux内核设计与实现》这本书 进入状态更快

    作者回复: 赞

    
     6
  • why
    2019-06-05
    - 多层组件统一完成进行读写文件的任务
        - 系统调用 sys_open, sys_read 等
        - 进程维护打开的文件数据结构, 系统维护所有打开的文件数据结构
        - Linux 提供统一的虚拟文件系统接口; 例如 inode, directory entry, mount, 以及对应操作 inode operations等, 因此可以同时支持数十种不同的文件系统
        - vfs 通过设备 I/O 层在通过块设备驱动程序访问硬盘文件系统
        - 通过缓存层加快块设备读写
    - 通过解析系统调用了解内核架构
    - 挂载文件系统 mount
        - 注册文件系统 register_filesystem 后才能挂载
        - 调用链 mount->do_mount->do_new_mount→vfs_kern_mount
        - 首先创建 struct mount
            - 其中 mnt_parent 指向父 fs 的 mount; mnt_parentpoint 指向父 fs 的 dentry
            - 用 dentry 表示目录, 并和目录的 inode 关联
            - mnt_root 指向当前 fs 根目录的 dentry; 还有 vfsmount 指向挂载树 root 和超级块
        - 调用 mount_fs 进行挂载
            - 调用 ext4_fs_type→mount(ext4_mount), 读取超级块到内存
            - 文件和文件夹都有一个 dentry, 用于与 inode 关联, 每个挂载的文件系统都由一个 mount 描述; 每个打开的文件都由 file 结构描述, 其指向 dentry 和 mount.
            - 二层文件系统根目录有两个 dentry, 一个表示挂载点, 另一个是上层 fs 的目录.
    - 打开文件 sys_open
        - 先获取一个未使用的 fd, 其中 task_struct.files.fd_array[] 中每一项指向打开文件的 struct file, 其中 fd 作为下标. 默认 0→stdin, 1→stdout, 2→stderr
        - 调用 do_sys_open->do_flip_open
            - 先初始化 nameidata, 解析文件路径名; 接着调用 path_openat
                - 生成 struct file 结构; 初始化 nameidata, 准备查找
                - link_path_walk 根据路径名逐层查找
                - do_last 获取文件 inode, 初始化 file
            - 查找路径最后一部分对应的 dentry
                - Linux 通过目录项高速缓存 dentry cache(dentry) 提高效率. 由两个数据结构组成
                    - 哈希表: dentry_hashtable; 引用变为 0 后加入 lru 链表; dentry 没找到则从 slub 分配; 无法分配则从 lru 中获取; 文件删除释放 dentry;
                    - 未使用的 dentry lru 链表; 再次被引用返回哈希表; dentry 过期返回给 slub 分配器
                - do_last 先从缓存查找 dentry, 若没找到在从文件系统中找并创建 dentry, 再赋给 nameidata 的 path.dentry; 最后调用 vfs_open 真正打开文件
                - vfs_open 会调用 f_op->open 即 ext4_file_open, 还将文件信息存入 struct file 中.
            - 许多结构体中都有自己对应的 operation 结构, 方便调用对应的函数进行处理
    展开
    
     4
  • Leon📷
    2019-06-04
    文章的核心就是把磁盘文件数据映射到进程中,可以把在磁盘的文件组织看成一种协议,内存中进程中的文件组织形式看成另外一种协议,内核就是这两个协议的中转proxy,带着这个主线看文章思路要明朗一些
      inode和dentry在一个文件系统挂载的时候怎么初始化和做好映射关系,这个是难点,我一开始也看懵逼了,后来一想,根文件系统不是挂载了各种磁盘分区的文件系统么,这个老师如果结合centos的xfs根文件系统下,可以挂载ext4的文件系统,并且用一个磁盘分区演示挂载,然后分析,可能大家更好理解,毕竟平时大家都是一个文件系统格式走到黑,个人建议这种复杂逻辑关系比如那个挂载图可以拍个动态图和视频,发个链接让大家去看看,
      

    作者回复: 赞,这个思路好啊

    
     3
  • Guarantee
    2019-06-16
    老师,您专栏中的图,用的是什么软件,还是就是PS做的图吗?

    作者回复: draw.io

    
     2
  • 陈志恒
    2019-11-25
    虚拟文件系统其实就是文件系统的数据结构,所以各个数据结构之间的关系要明白,作者在最后已经画出来了!背了它!
    
     1
  • thomas
    2019-09-23
    老师,我的理解第一张图中的page cache,应该是buffer吧,而page cache是在VFS这一层
    
     1
  • oldman
    2019-07-20
    想问问老师,怎么才能学好C语言

    作者回复: 看书,写代码

    
     1
  • Leon📷
    2019-06-04
    我再补充总结一下
    第一 文章讲的是格式化一个磁盘并且mount到系统根目录
    第二 进程创建过程中跟文件的交互过程,包括打开,创建,当然修改删除老师没讲
    进城文件系统这个我有点疑惑之前老师讲进程task struct有提过,希望老师指点指点
    大家可以自己格式化一个盘ext4,然后strace mount /dev/sdc /test_flash > mntout 2>&1
    我追踪的关于mount的如下
    execve("/bin/mount", ["mount", "/dev/sdc", "/test_flash"], [/* 26 vars */]) = 0
    open("/lib64/libmount.so.1", O_RDONLY|O_CLOEXEC) = 3
    lstat("/run/mount/utab", 0x7ffebb0a8130) = -1 ENOENT (No such file or directory)
    mkdir("/run/mount", 0755) = -1 EEXIST (File exists)
    stat("/run/mount/utab", 0x7ffebb0a8020) = -1 ENOENT (No such file or directory)
    stat("/run/mount", {st_mode=S_IFDIR|0755, st_size=40, ...}) = 0
    access("/run/mount", R_OK|W_OK) = 0
    stat("/sbin/mount.ext4", 0x7ffebb0a6fc0) = -1 ENOENT (No such file or directory)
    stat("/sbin/fs.d/mount.ext4", 0x7ffebb0a6fc0) = -1 ENOENT (No such file or directory)
    stat("/sbin/fs/mount.ext4", 0x7ffebb0a6fc0) = -1 ENOENT (No such file or directory)
    mount("/dev/sdc", "/test_flash", "ext4", MS_MGC_VAL, NULL) = 0
    展开
    
     1
  • 花晨少年
    2020-01-20
    我理解page cache那一层应该是缓冲区,而page cache应该在文件系统上面
    
    
  • 俩孩儿他爸
    2019-12-19
    对于总结中的那副图,进程A和进程B都打开了stderr文件,但是,图中表示的是两个stderr文件描述符指向了同一个struct file结构。理论上,这个进程的stderr应该对应不同的struct file才对,应为struct file依附于进程的,进程每打开文件,内核就会相应的创建一个struct file与之对应。
    
    
  • 深寒丶
    2019-11-13
    老师,你说dentry最重要的作用是指向inode,但是 struct file不是已经指向inode了么
    
    
  • zhj
    2019-10-11
    在vfs_kern_mount函数中
    mnt->mnt.mnt_root = root;
        mnt->mnt.mnt_sb = root->d_sb;
        mnt->mnt_mountpoint = mnt->mnt.mnt_root;
        mnt->mnt_parent = mnt;

    这不是说明新分配的mount的挂载点就是vfsmount中的mnt_root
    mnt_parent 就是新分配的mount
    和上文讲到的二者dentry不一致 且 mount的父mount说的不一致
    展开
    
    
  • williamcai
    2019-10-08
    老师,你好,在dcache中没有找到文件,就会创建一个,这个新创建的文件要不要放入dcache中?
    
    
  • 计算机班陈公子
    2019-09-13
    有一点疑惑的就是,是不是一个进程打开一个文件会新建两个struct,一个是file struct他会放进files_struct数组里面,这个file stuct里面拥有inode信息。然后还会新建一个dentry struct,里面也有inode的信息?我看专栏中说这两个struct都是在文件打开后新建的,那这两个作用是否重复?还是说因为dentry还保留了mount的信息?
    
    
  • 莫名
    2019-08-22
    `inode 结构就表示硬盘上的 inode,包括块设备号等。` 这个说法不太准确。inode结构体是磁盘文件inode的内存表示,磁盘文件的inode不包含引用计数之类的东西,被读取至内存,使用inode结构体表示。

    作者回复: inode结构就是用来“表示”硬盘上的inode。inode结构体是磁盘文件inode的内存表示,我也是这个意思的

    
    
  • Geek_54edc1
    2019-06-20
    如何维护跨文件系统的文件夹和文件的关系:通过dentry在操作系统层面来维护,dentry和inode关联,而且dentry里有parent、child、subdirs这些成员,正好对应文件夹和文件之间的关系

    作者回复: 在内存里面,也有superblock的,会关联dentry

    
    
  • Geek_54edc1
    2019-06-20
    老师您好,请教一个问题:lookup_open创建新的dentry后,会把新的dentry加到dentry cache里吗?

    作者回复: 会的

    
    
  • Spring
    2019-06-11
    从文章可以看出,父文件系统的挂载点其实就是子文件系统挂载的地方,比如文章中的A文件系统挂载在根文件系统的home目录下,那home是根文件系统的一个挂载点。
    另外,我有一个疑问:data是一个文件,而dentry是一个目录,为什么data文件struct file的dentry指向一个叫data的dentry呢?明明没有data目录呀?

    作者回复: dentry不仅仅表示目录,也可以表示文件

    
    
  • 刘強
    2019-06-03
    老师,实在是不理解home目录为什么是根文件系统的挂载点,难道不是那个“/”吗?我一直理解的挂载点就是挂载文件系统的那个目录,希望老师抽个时间,指点一下挂载目录和挂载点的区别,看了一天了,谢谢。

    作者回复: home是在根文件系统上的一个挂载点

    
    
  • Sharry
    2019-06-03
    老师的挂载文件系统个人感觉没有错, 我的理解如下

    - 第一层
      - mount: 根文件系统描述
      - dentry: 根文件系统路径
      - file: 根文件系统对应的文件
        - vfsmount: 指向该文件的文件系统
        - dentry: 指向该文件的路径
    - 第二层
      - mount: 文件系统 A 的描述
      - dentry: 文件系统 A 的根路径
      - file: 文件系统 A 的目录文件
    - 第三层
      - mount: 文件系统 B 的描述
      - dentry: 文件系统 B 的根路径
      - file: 文件系统 B 的目录文件
    - 第四层
      - dentry: 文件系统 B 中 world 文件夹路径
      - file: 文件系统 B 中的文件
    - 第五层
      - dentry: 文件系统 B 中 world 文件夹下的文件路径
      - file: 文件系统 B 中 world 文件夹下的文件
    展开
    
    
我们在线,来聊聊吧