首发:嵌入式客栈
作者:逸珺
1. 概述
通常地,Linux操作系统如下图所示,由四大子系统组成:
- 用户应用层: 特定Linux系统上使用的应用程序集会有所不同,具体取决于计算机系统的用途,但典型示例包括文字处理应用程序和Web浏览器,嵌入式Linux往往会进行大量的裁剪,将不需要的应用裁剪掉。
- O/S 服务层: O/S服务通常被认为是操作系统的一部分(窗口系统,命令外壳等);此外,该子系统还包含内核的编程接口(编译器工具和库d)
- Linux内核层:这是本文关注的主要子系统,内核抽象并调控对硬件资源(包括CPU)的访问。
- 硬件控制层:该子系统由Linux安装中的所有可能的物理设备组成;例如,CPU,内存硬件,硬盘和网络硬件都是该子系统的成员
2.内核架构
2.1 内核之作用
- Linux内核为用户进程提供了虚拟机接口。 进程编程无需知道计算机上安装了什么物理硬件,Linux内核将所有硬件抽象为一致的虚拟接口。
- 此外,Linux以对用户进程透明的方式支持多任务:每个进程都可以像它是计算机上唯一的进程一样工作,并且专用于占用主内存和其他硬件资源。内核实际上同时运行多个进程,并负责中介对硬件资源的访问,以便在维护进程间安全性的同时,每个进程都具有公平的访问权限。
2.2 内核之结构
内核主要由以下五大组成部分:
- 进程调度器(SCHED)负责控制对CPU的进程访问。调度程序执行一项调度策略,以确保进程可以公平地访问CPU,同时确保内核按时执行必要的硬件操作。
- 内存管理器(MM)允许多个进程安全地共享机器的主内存系统。此外,内存管理器还支持虚拟内存,该虚拟内存允许Linux支持使用的内存量超过系统可用内存的进程。使用文件系统将未使用的内存换出到持久性存储,然后在需要时交换回来。
- 虚拟文件系统(VFS)通过为所有设备提供通用文件接口来抽象化各种硬件设备的详细信息。此外,VFS支持几种与其他操作系统兼容的文件系统格式。
- 网络接口(NET)提供对几种网络标准和各种网络硬件的访问。
- 进程间通信(IPC)子系统实现在单个Linux系统上进行进程间通信的多种机制。
从依赖性的角度分析:
- 进程调度程序子系统使用内存管理器为恢复特定进程的特定进程调整硬件内存映射。
- 进程间通信子系统依赖于内存管理器来支持共享内存通信机制。此机制允许两个进程除了访问其通常的私有内存之外,还访问公共内存的区域。
- 虚拟文件系统使用网络接口来支持网络文件系统(NFS),并且还使用内存管理器来提供ramdisk设备。
- 内存管理器使用虚拟文件系统来支持交换;这是内存管理器依赖进程调度程序的唯一原因。当某个进程访问当前已换出的内存时,内存管理器会向文件系统发出请求,从持久性存储中获取内存,并挂起该进程。
2.3 内核之重要数据结构
- 任务链表(Task List):流程调度程序为每个活动的流程维护一个数据块。这些数据块存储在称为任务列表的链接列表中。进程调度程序始终维护一个指示当前活动进程的当前指针。
- 内存映射(memry map):内存管理器基于每个进程存储虚拟地址到物理地址的映射,还存储有关如何获取和替换特定页面的其他信息。此信息存储在内存映射数据结构中,该结构存储在流程调度程序的任务列表中。
- 索引节点(I-node):虚拟文件系统使用索引节点(索引节点)表示逻辑文件系统上的文件。索引节点数据结构存储文件块号到物理设备地址的映射。如果两个进程打开了相同的文件,则可以在多个进程之间共享I节点数据结构。共享是通过两个任务数据块指向相同的i节点来完成的。
- 数据连接(Data Connection) 所有数据结构都植根于流程调度程序的任务列表。系统上的每个进程都有一个数据结构,该数据结构包含一个指向其内存映射信息的指针,以及指向代表所有打开文件的i节点的指针。最后,任务数据结构还包含指向数据结构的指针,该数据结构表示与每个任务关联的所有打开的网络连接。
3.各子系统架构分析
3.1 进程调度器架构
进程调度器是Linux内核中最重要的子系统。其目的是控制对计算机CPU的访问。这不仅包括用户进程的访问,还包括其他内核子系统的访问。
由上图可知,进程调度器可分为四大模块:
- 调度策略模块负责判断哪个进程可以访问CPU;设计该策略是为了使进程可以公平地访问CPU。
- 体系结构相关模块特定于体系结构的模块设计有一个公共接口,用于抽象任何特定计算机体系结构的详细信息。这些模块负责与CPU通信以挂起和恢复进程。这些操作涉及知道每个进程需要保留哪些寄存器和状态信息,并执行汇编代码以执行挂起或恢复操作。
- 体系结构无关模块与体系结构无关的模块与策略模块进行通信,以确定下一步将执行哪个进程,然后调用特定于体系结构的模块以恢复适当的进程。此外,此模块调用内存管理器以确保为恢复的过程正确还原了内存硬件
- 系统调用接口模块允许用户进程仅访问内核显式导出的那些资源。这将用户进程对内核的依赖性限制为一个定义良好的接口,尽管其他内核模块的实现发生了变化,该接口很少更改
进程调度器维护一个数据结构,即任务列表,每个活动进程具有一个条目。此数据结构包含足够的信息来暂停和恢复过程,但还包含其他记帐和状态信息。该数据结构可在整个内核层公开使用。
如前所述,进程调度程序将调用内存管理器子系统。因此,进程调度程序子系统依赖于内存管理器子系统。此外,所有其他内核子系统都依赖进程调度程序来挂起和恢复进程,同时等待硬件请求完成。这些依赖关系通过函数调用和对共享任务列表数据结构的访问来表示。所有内核子系统都读取和写入代表当前任务的数据结构,从而导致整个系统中的双向数据流。
除了内核层中的数据和控制流之外,O / S服务层还为用户进程提供了一个接口,用于注册计时器通知。这对应于[Garlan 1994]中描述的隐式执行体系结构样式。这导致控制从调度程序流向用户进程。恢复休眠过程的通常情况在正常情况下不视为控制流程,因为用户进程无法检测到此操作。最后,调度程序与CPU通信以挂起和恢复进程。这导致数据流和控制流。CPU负责中断当前正在执行的进程,并允许内核调度另一个进程。
3.2 内存管理器架构
内存管理器子系统负责控制对硬件内存资源的进程访问。这是通过硬件内存管理系统完成的,该系统提供了进程内存引用与机器物理内存之间的映射。内存管理器子系统在每个进程的基础上维护此映射,以便两个进程可以访问相同的虚拟内存地址并实际使用不同的物理内存位置。此外,内存管理器子系统还支持交换。它将未使用的内存页面移至持久性存储,以使计算机支持的虚拟内存多于物理内存。
3.2.1 模块结构分析
内存管理器主要由以下三个模块组成:
- 体系结构相关模块为内存管理硬件提供了虚拟接口
- 体系结构无关模块执行所有的每个进程映射和虚拟内存交换。此模块负责确定在出现页面错误时将收回哪些内存页面-由于没有预期将需要更改此策略,因此没有单独的策略模块。
- 系统调用接口模块提供对用户进程的受限访问。该接口允许用户进程分配和释放存储,还可以执行内存映射文件I / O。
3.2.2 从数据表征的角度分析
内存管理器存储物理地址到虚拟地址的每个进程的映射。该映射作为参考存储在流程调度程序的任务列表数据结构中。除了此映射之外,数据块中的其他详细信息还告诉内存管理器如何获取和存储页面。例如,可执行代码可以将可执行映像用作后备存储,但是必须将动态分配的数据备份到系统页面文件中。最后,内存管理器在此数据结构中存储权限和记帐信息,以确保系统安全。
3.2.3 数据流,控制流和依赖关系
内存管理器控制内存硬件,并在发生页面错误时从硬件接收通知-这意味着内存管理器模块和内存管理器硬件之间存在双向数据和控制流。另外,内存管理器使用文件系统来支持交换和内存映射的I / O。此要求意味着内存管理器需要对文件系统进行过程调用以存储和从持久性存储中获取内存页面。由于无法立即完成文件系统请求,因此内存管理器需要暂停一个过程,直到将内存换回为止。此要求导致内存管理器对过程调度程序进行过程调用。同样,由于每个进程的内存映射都存储在进程调度程序的数据结构中,因此在内存管理器和进程调度程序之间存在双向数据流。用户进程可以在进程地址空间内设置新的内存映射,并可以注册自己以在新映射的区域内通知页面错误。这引入了从内存管理器到系统调用接口模块再到用户进程的控制流。从传统意义上讲,没有来自用户进程的数据流,但是用户进程可以使用系统调用接口模块中的选择系统调用从内存管理器中检索某些信息。
3.3 虚拟文件系统架构
虚拟文件系统旨在提供存储在硬件设备上的数据的一致视图。计算机中几乎所有的硬件设备都是使用通用设备驱动程序接口表示的。虚拟文件系统进一步发展,并允许系统管理员在任何物理设备上安装一组逻辑文件系统中的任何一个。逻辑文件系统促进与其他操作系统标准的兼容性,并允许开发人员使用不同的策略来实现文件系统。虚拟文件系统抽象了物理设备和逻辑文件系统的详细信息,并允许用户进程使用通用接口访问文件,而不必知道文件驻留在哪个物理或逻辑系统上。
除了传统的文件系统目标之外,虚拟文件系统还负责加载新的可执行程序。该责任由逻辑文件系统模块完成,这使Linux支持多种可执行格式。
故简言之:
- 抽象物理设备和逻辑文件系统的详细信息,提供公共访问接口。
- 提供通用的设备驱动程序接口。
- 加载新的可执行程序。
3.3.1 模块结构分析
可分为四大模块:
- 公共驱动抽象模块 由于存在大量不兼容的硬件设备,因此存在大量的设备驱动程序。Linux系统最常见的扩展是添加了新的设备驱动程序。设备独立接口模块提供了所有设备的一致视图。
- 逻辑文件系统模块,每个支持的文件系统都有一个逻辑文件系统模块。
- 系统独立接口层提供了硬件资源与硬件和逻辑文件系统无关的视图。该模块使用面向块或面向字符的文件接口显示所有资源。
- 系统调用接口层为用户进程提供对文件系统的受控访问。虚拟文件系统仅将特定功能导出到用户进程。
3.4 网络接口层架构
网络子系统允许Linux系统通过网络连接到其他系统。支持许多可能的硬件设备,以及可以使用的许多网络协议。网络子系统抽象了这两个实现细节,因此用户进程和其他内核子系统可以访问网络而不必知道正在使用什么物理设备或协议。
3.4.1 模块结构组成
- 网络设备驱动程序负责与硬件设备通信。每个可能的硬件设备都有一个设备驱动程序模块。
- 设备无关的接口模块提供了所有硬件设备的一致视图,因此子系统中的更高级别不需要特定的使用硬件知识。
- 网络协议模块负责实现每种可能的网络传输协议。
- 协议无关接口模块提供独立于硬件设备和网络协议的接口。这是接口模块,其他内核子系统使用该接口模块访问网络,而无需依赖特定的协议或硬件。
简言之,
- 网络设备驱动实现底层硬件的控制
- 设备独立接口层为上层提供对底层设备驱动层实现统一访问接口
- 网络协议层实现不同的网络协议
- 协议独立接口层用以抽象隐藏不同硬件、不同网络协议
推荐阅读
更多硬核嵌入式技术干货请关注嵌入式客栈专栏。