41

从文件系统的数据结构看 Linux 内核设计

 5 years ago
source link: https://mp.weixin.qq.com/s/iItbscZ7V6_Kmmtq_KAaHQ?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

作者简介

赵晨雨:西安邮电大学2018级陈莉君教授研究生,天真无邪小白一枚,已经爱上linux内核而不能自拔,正在成长为内核狂热爱好者 :japanese_ogre:

跟随陈老师学习linux内核两个月了,对linux内核产生了极大的兴趣,最近学习文件系统,有一些自己的看法,很荣幸能在linux内核之旅进行分享^_^

iaEFruE.gif

本篇文章使用尽量 通俗 的语言来说明linux内核文件系统中各个数据结构之间的关系,这是一个很复杂的结构关系,在学习这里的时候一定要和源代码一一对应起来,否则的话就会陷入迷茫之中。由于linux内核足够复杂,就会有多种解释方式,我认为所有关于linux内核的书籍,都是不同作者对内核的不同的看法,说不定这些看法对于linus本人来说都是很巧妙的,所以我在这里也大胆地提出自己对linux内核设计方式的一些看法。

话不多说,我们上图:

QraQJ33.jpg!web

If2Iry6.gifIf2Iry6.gifIf2Iry6.gif      我使用这张结构图来进行说明,一共大概有10个结构体,我把它分成三条线来看,在图中也标记好了,在看每一条线时,我们把它从整体结构中隔离出来看。

第一条线( 绿色

这一条线是进程部分,也就是以进程的眼光来看文件系统。task_struct是一个非常复杂的结构体,我们在这里只看与文件系统相关的字段。从现在开始,把自己当成一个内核设计者,接下来将要介绍的数据结构都是为了给进程提供完好的服务,使得进程可以正常运行。(这里也可以体会到进程真的是OS的核心)

首先,进程在运行的时候,总归会使用到文件,那么就会用open()和close()两个函数,此时,就会产生图中的第1个结构体file,另外进程使用到的文件是很多的,所以会有很多个file(这里说明一下,file还有一个很好的作用是并发访问,不同的用户在打开相同文件的时候都会产生file,这样就可以实现互不干扰)产生,那么这个时候就需要对这些file结构体进行管理,按照内核的标准套路,就是使用唯一标号,我们叫它文件描述符,那么自然而然地,我们可以想到,这么多文件描述符我们怎么管理呢?再按照内核的标准套路,我们把它又封装成一个结构体,这个结构体最主要的任务就是把这么多file结构体进行很有条理的管理,从而方便进程的使用。这个结构体就是图中第2个files_struct结构体了,看图中的红线,一个二级指针指向fd_arry数组,数组里存放着一个又一个的file结构体的地址,最重要的我们要让PCB能够使用到这个结构体,就放入一个字段files指向files_struct。

(file结构体之后的dentry结构体部分先保留。)

第二条线( 红紫色

这一条线是纯正的文件系统线,也就是我们现在是文件系统,我现在需要正确的进入内核。

首先,每一种文件系统都需要符合VFS的规定和内核的标准套路,我是一个文件系统,那么我的条条框框就很多,也就是字段特别多,为了融入内核,我需要通过图中第3个结构体file_system_type来进行注册,换句话说,内核中有多少个文件系统,就有多少个file_system_type结构体。之后,我是文件系统,我自然而然就需要使用磁盘来存放文件了,那么这个时候有会有很多很多的细节,也就是存放在块设备上的管理信息,这些信息又有很多,那么按照内核的设计套路,再次封装成一个结构体,也就是图中第4个结构体super_block结构体。我在这里有一个疑问,就是一个file_system_type和一个super_block,这两个有什么区别又有什么关系呢?因为我觉得只需要一个就够了。在阅读大量书籍后,我自己给出的答案是file_system_type是描述这个文件系统的,而super_block是用来实际管理文件系统的,二者是不同的作用,就好比注册完以后,那张注册表还有别的作用吗?

super_block也是一个极其庞大的结构体,它既然处于管理的地位,所以具体的一个个文件就需要和它进行关联,按照内核标准套路,一个个具体的文件在内核中还是抽象成一个结构体,就是图中的第5个结构体inode结构体,(多说一句,这两个结构体之间是互联的,各自有指针指向对方,而且文件系统这里的指针真的很精彩!),那么inode代表了一个个实际的文件,这时候,自然而然就需要目录了,内核把目录也当做一个文件来处理,同样抽象成一个结构体,也就是图中的第6个结构体dentry结构体。

一二条线的交叉部分

这里的交叉部分很巧妙,我学习文件系统的时候,是从super_block开始学习的,所以顺着下来是inode结构体,但是当时就在 为什么不先是dentry目录,然后目录下再存放inode呢? 我自己的 答案 是:

  • 站在第二条线来想,所谓目录,是对文件的划分,所以得先有文件,然后才能有目录。

  • 站在第一条线来想,我要打开一个文件,这个文件已经存在了,那么我就需要从目录中去找,然后再往下找到inode

综合两条线来看,正是因为内核的这种设计方式,我们才会有在打开一个文件时先找目录的习惯。

再次来体会图中的交叉部分,dentry是很巧妙的。

第三条线( 蓝紫色

我们直接来看图中的第7个结构体,vfsmount结构体,这里先说一下为什么会有这么个结构,我们在第二条线中说过了文件系统注册时的file_struct_type结构体了,但这个信息还不够,我们要正确使用一种文件系统,就必须mount到根文件系统的某个目录上去,记得要root权限哦,这个时候还是为了管理上的方便,又抽象出来一个结构体vfsmount,它存放的就是文件安装的相关信息,它和PCB之间还需要建立连接,这里又通过第8个结构体来建立连接,它在2.6源码中名字是namespace(2.4中是mnt_namespace)。

从文件系统来看内核

这里假设大家已经细读了内核源码,我们可以发现,内核设计的标准套路,就是 抽象、管理、操作 抽象 是分为两种情况,一种是外部文件的抽象,一种是内部信息复杂而进行的抽象。那么是怎么进行 管理 的呢?举个例子来说,只要内核中有许多独立的结构体存在时,我们就通过双向链表,单项链表,哈希表这些方式进行管理。这里可以体会一下数据结构的精华所在。 操作 的对象就是我们所抽象的一个个数据结构。我们在上面仅仅介绍了这几个结构的关系,它们还只是数据结构而已,我们还需要操作,就是调用内核的API了,这些API的工作就是传递数据,从这个结构体中拿出数据放到另外的一个结构体中,所以所谓内核的运行,就是我们抽象出来的数据结构中数据的流动,在我们的脑海里可以形成一个很壮观的动态的场面。并且我始终坚信,内核所有解决问题的策略,都可以在我们现实生活中找到影子,毕竟,内核是人写出来的嘛!

RnMr2mU.gif

学习内核的方法

这里推荐一下将内核划分的学习方法(这种方法在高剑林老师的书中有详细的介绍)。也就是将内核代码分成基础部分和应用部分(注意这里是将内核再划分哦)。我们在学习内核代码时,应用部分占用了大多数,基础部分的规模并不大,而且各个版本之间改动幅度很小,并且相当的短小精悍。我们可以这样来看,在用户台下,我们的程序要执行,需要调用内核的系统函数,那么我们可以类似的把内核再分成“用户态”和“内核态”,“用户态”就是应用部分,“内核态”就是基础部分,应用部分想要执行,就需要调用基础部分。

按照上面的介绍,基础部分也是一个小内核,那么它就需要给外界提供服务,换句话说,就是它的内部也具有自己的数据结构和函数:

  • 数据结构:

    • 双向链表

    • hash链表

    • 单向链表

    • 红黑树

    • radix树

  • 服务:

    • 内核中使用内存

    • 内核中的任务调度

    • 软中断和tasklet

    • 工作队列

    • 自旋锁

    • 内核信号量

    • 原子变量

这种方法主要对应前面介绍的内核设计套路中的管理环节,我们可以通过这种方法打破对内核的恐惧感,因为内核无非就是使用这些基础部分来管理数据,而数据的组织方式在内核中是最复杂的,例如说文件系统这里存在大量的全局链表,拿inode_in_use和inode_in_unused来说,我们就会很奇怪,为什么要有这两个链表?那么运用这种方法我们就可以这样来想,内核设计者在设计的时候,遇到了一个实际问题,这个问题一般可以从链表的名字看出来,这里就是遇到了区分inode有没有使用的问题,那么自然而然就可以想到,使用基础部分的各种链表来进行管理,因为这些链表在内核中就是负责处理这种问题的。所以,我们在学习内核的时候,心中有这些基本部分的概念,再来看内核就是另一种角度了。

由于自己接触linux内核时间不长,才疏学浅,班门弄斧了,如果有错误的地方欢迎大家指正,小赵万分感谢:-D


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK