大家都知道源理君很多期的文章都是关于linux内核的功能,本着公众号的原则,只讲原理,将复杂的代码转换为通俗易懂的文字,图片。最后呈现给大家。可以源理君一直没有从大框架上系统的给各位梳理Linux内核体系结构。那本文就一个目的,站在山顶向下看。
从图中我们可以分为两个层次:
在最上层是用户空间,也就是运行应用程序。用户空间的下层就是经常使用的gblic库,它的作用就是封装系统调用接口。不使用gblic库,而大量的直接使用系统调用接口是非常不明智的选择。用户空间运行的进程,他们各自拥有独立的虚拟地址空间,而内核则有单独的地址空间。
下层就是内核空间了。Linux内核空间又分为了三层:
Linux 内核实现了很多重要的体系结构属性。在或高或低的层次上,内核被划分为多个子系统。Linux 也可以看作是一个整体,因为它会将所有这些基本服务都集成到内核中。这与微内核的体系结构不同,后者会提供一些基本的服务,例如通信、I/O、内存和进程管理,更具体的服务都是插入到微内核层中的。每种内核都有自己的优点,不过这里并不对此进行讨论。
随着时间的流逝,Linux 内核在内存和 CPU 使用方面具有较高的效率,并且非常稳定。但是对于 Linux 来说,最为有趣的是在这种大小和复杂性的前提下,依然具有良好的可移植性。Linux 编译后可在大量处理器和具有不同体系结构约束和需求的平台上运行。一个例子是 Linux 可以在一个具有内存管理单元(MMU)的处理器上运行,也可以在那些不提供 MMU 的处理器上运行。Linux 内核的 uClinux 移植提供了对非 MMU 的支持。
Linux内核的主要组件有:
(1)系统调用接口
系统调用层提供了某些机制执行从用户空间到内核的函数调用。它是依赖真个体系结构的。在这一层提供多路复用和多路分解服务。
(2)进程管理
进程管理的核心就是进程的调度。在Linux内核中,进程调度的单元是进程,线程对与调度来说相当于进程概念。内核通过系统调用提供了应用程序编程接口。例如:创建新进程(fork,exec),结束进程(kill, exit),并且提供了控制进程,同步进程和进程间通信的接口。
进程管理还包括处理活跃进程之间共享CPU的需求。内核使用的是CFS完全公平调度器,在我之前文章《Linux完全公平调度器CFS》有详细阐述。
(3)内存管理
内核所管理的另外一个重要资源是内存。源理君的另一篇文章《搞懂Linux内存管理,仅此一篇》有详细讲解Linux内存管理。为了提高效率,引入了虚拟内存的概念,内存是按照所谓的内存页 方式进行管理的(一般一个内存页大小 4KB和8KB,绝大部分为4KB)。Linux 不仅管理可用内存的方式,以及物理和虚拟映射所使用的硬件机制。不过内存管理要管理的可不止 4KB 缓冲区。Linux 提供了对 4KB 缓冲区的抽象,例如 slab 分配器。这种内存管理模式使用 4KB 缓冲区为基数,然后从中分配结构,并跟踪内存页使用情况,比如哪些内存页是满的,哪些页面没有完全使用,哪些页面为空。这样就允许该模式根据系统需要来动态调整内存使用。为了支持多个用户使用内存,有时会出现可用内存被消耗光的情况。由于这个原因,页面可以移出内存并放入磁盘中。这个过程称为交换,因为页面会被从内存交换到硬盘上。内存管理的源代码可以在 ./linux/mm 中找到。
(4)虚拟文件系统
虚拟文件系统(VFS)是 Linux 内核中非常有用的一个方面,因为它为文件系统提供了一个通用的接口抽象。VFS 在 系统调用 和内核所支持的文件系统之间提供了一个屏蔽层。如下图所示:
在 VFS 上面,是对比如open、close、read 和 write 之类的函数的一个通用 API 抽象。在 VFS 下面是文件系统抽象,它定义了上层函数的实现方式。它们是给定文件系统(超过 50 个)的插件。文件系统的源代码可以在 ./linux/fs 中找到。文件系统层之下是缓冲区缓存,它为文件系统层提供了一个通用函数集(与具体文件系统无关)。这个缓存层通过将数据保留一段时间(或者随即预先读取数据以便在需要是就可用)优化了对物理设备的访问。缓冲区缓存之下是设备驱动程序,它实现了特定物理设备的接口。
(5)网络协议栈
网络协议栈在设计上遵循模拟协议本身的分层体系结构。回想一下,Internet Protocol (IP) 是传输协议(通常称为传输控制协议或 TCP)下面的核心网络层协议。TCP 上面是 socket 层,它是通过系统调用层进行调用的。socket 层是网络子系统的标准 API,它为各种网络协议提供了一个用户接口。从原始帧访问到 IP 协议数据单元(PDU),再到 TCP 和 User Datagram Protocol (UDP),socket 层提供了一种标准化的方法来管理连接,并在各个终点之间移动数据。内核中网络源代码可以在 ./linux/net 中找到。
(6)设备驱动程序
Linux 内核中有大量代码都在设备驱动程序中,它们能够运转特定的硬件设备。Linux 源码树提供了一个驱动程序子目录,这个目录又进一步划分为各种支持设备,例如 Bluetooth、I2C、serial 等。设备驱动程序的代码可以在 ./linux/drivers 中找到。
(7)依赖体系结构的代码
尽管 Linux 很大程度上独立于所运行的体系结构,但是有些元素则必须考虑体系结构才能正常操作并实现更高效率。./linux/arch 子目录定义了内核源代码中依赖于体系结构的部分,其中包含了各种特定于体系结构的子目录(共同组成了 BSP)。对于一个典型的桌面系统来说,使用的是 x86 目录。每个体系结构子目录都包含了很多其他子目录,每个子目录都关注内核中的一个特定方面,例如引导、内核、内存管理等。这些依赖体系结构的代码可以在 ./linux/arch 中找到。
Linux 还是一个动态内核,支持动态添加或删除软件组件。被称为动态可加载内核模块,它们可以在引导时根据需要(当前特定设备需要这个模块)或在任何时候由用户插入。
源理君参考了这篇文章 https://blog.csdn.net/zhoudaxia/article/details/7172192