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

栏目: 后端 · 发布时间: 5年前

作者简介

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

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

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

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

话不多说,我们上图:

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

从文件系统的数据结构看 Linux 内核设计 从文件系统的数据结构看 Linux 内核设计 从文件系统的数据结构看 Linux 内核设计       我使用这张结构图来进行说明,一共大概有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的工作就是传递数据,从这个结构体中拿出数据放到另外的一个结构体中,所以所谓内核的运行,就是我们抽象出来的数据结构中数据的流动,在我们的脑海里可以形成一个很壮观的动态的场面。并且我始终坚信,内核所有解决问题的策略,都可以在我们现实生活中找到影子,毕竟,内核是人写出来的嘛!

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

学习内核的方法

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

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

  • 数据结构:

    • 双向链表

    • hash链表

    • 单向链表

    • 红黑树

    • radix树

  • 服务:

    • 内核中使用内存

    • 内核中的任务调度

    • 软中断和tasklet

    • 工作队列

    • 自旋锁

    • 内核信号量

    • 原子变量

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

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


以上所述就是小编给大家介绍的《从文件系统的数据结构看 Linux 内核设计》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java并发编程的艺术

Java并发编程的艺术

方腾飞、魏鹏、程晓明 / 机械工业出版社 / 2015-7-1 / 59.00元

并发编程领域的扛鼎之作,作者是阿里和1号店的资深Java技术专家,对并发编程有非常深入的研究,《Java并发编程的艺术》是他们多年一线开发经验的结晶。本书的部分内容在出版早期发表在Java并发编程网和InfoQ等技术社区,得到了非常高的评价。它选取了Java并发编程中最核心的技术进行讲解,从JDK源码、JVM、CPU等多角度全面剖析和讲解了Java并发编程的框架、工具、原理和方法,对Java并发编......一起来看看 《Java并发编程的艺术》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

html转js在线工具
html转js在线工具

html转js在线工具