★最近正在整理操作系统相关的知识,但是由于时间比较紧张,所以就没整理成相应的文档,而整了一份思维导图(推文的内容是根据思维导图的内容自动转换出来的),但是这份思维导图其实已经包含了具体内容。接下去,我还会整理出以下几个大块的思维导图:进程管理(包含进程通信、同步原语等)、内存管理、文件系统、设备管理、系统虚拟化。 ”
后台发送“OS”即可获得清晰版的思维导图
操作系统概述
什么是操作系统
- 对硬件进行管理和抽象
- 将硬件抽象成不依赖具体硬件特性的资源,即将有限的、离散的资源高校地抽象成无限的、连续的资源,并将硬件通过易用的接口提供给上层应用,使应用无须关心硬件的具体细节。比如,应用开发者无须关心物理内存硬件的型号、位置和容量,而是面向一个统一的、近似无限的虚拟地址空间。
- 将复杂的、具备不同功能的硬件资源纳入统一的管理。比如,识别出多种不连续的、有限的物理内存区域的起始地址和大小,并使用物理内存分配器进行管理。
- 管理硬件
- 对硬件进行抽象
- 为应用提供服务并进行管理
- 负责对应用生命周期的管理,包括应用的加载、启动、切换、调度、销毁等。这样,操作系统能够从全局角度对资源进行分配,从而保证应用间的公平性、性能与安全的隔离性。
- 操作系统提供各种不同层次、不同功能的接口(如系统调用)以满足应用的需求,还提供不同类型的访问控制、应用间交互等服务。通过这些接口和服务,操作系统将应用从繁杂的系统工作中解放出来。
- 服务于应用
- 管理应用
操作系统的目标
- 建立抽象,让系统方便和易于使用
- 提供高性能,最小化操作系统自身的开销
- 应用程序之间以及 OS 和应用程序之间必须提供保护
- 高度的可靠性,操作系统必须不间断运行
- 其他:能源效率、安全性
操作系统发展简史
- GM-NAA I/O:第一个(批处理)操作系统
- 1946年2月14日,世界上公认的第一台通用计算机 ENIAC 在美国宾夕法尼亚大学诞生
- 1956年,实现了第一个公认的操作系统 GM-NAA I/O
- OS/360:从专用走向通用
- 1964年,IBM发布了名为 IBM System/360 大型机。他有两大突破:
- 通过定义对应的指令集架构(Instruction Set Architecture,ISA),将计算机的架构与实现分开,从而在一套架构上可以实现多代计算机。
- 由于架构与具体实现的分离,使得操作系统从面向每种计算机的定制转变为与计算机底层硬件实现相解耦。
- Multics/Unix/Linux:分时与多任务
- 1964 年通用电气和麻省理工学院联合发起了 Multics,目标是多用户、多任务、多层次的操作系统,使用了分时的概念,并首次将文件与内存分离,还提出和实现了文件系统、动态链接、CPU/内存、磁盘的热替换、特权级分层、命令处理器(后来的Shell)等开创性概念。
- 1969 年,UNIX 提出了 Shell。
- 1991年 Linus Torvalds 发布了 Linux 操作系统
- macOS/Windows:以人为本的人机交互
- 1973 年,Xerox Alto 第一个图形化操作系统,并首次使用了鼠标。
- 1979 年,Steve Jobs 访问 Xero PARC,意识到 GUI 的重要性,然后在 1983 年发布了 Apple Lisa,也就是后来的 Macintosh。
- 1985 年,Windows 1.0
操作系统接口
- 系统调用接口
- POSIX(Portable Operating System Interface for UNIX) 接口
- 由于每个操作系统提供的系统各不相同,为了同一个应用程序在不同操作系统上的可移植性,逐渐生成一些可移植操作系统接口标准,比如 POSIX 标准。
POSIX 是为了让应用可以同时在不同 UNIX 操作系统上运行而制定的一套标准的操作系统 API。
POSIX 标准通常通过 C library(libc)来实现,比如 glibc、musl、eglibc。那么应用程序只需要调用 libc 提供的接口就可以实现对操作系统的功能调用,同时也实现了应用在类 UNIX 系统(包括Linux)上的可移植性。不同的操作系统通过移植 libc 也可以来实现对现有的应用生态的支持。
- 领域应用接口
- Android
- ROS
- 在 POSIX 或者系统调用的基础之上继续封装面向不同领域的领域应用接口。
内核概述
什么是内核
内核的能力
内核种类
- 简要结构
- 将应用程序与操作系统放置在同一个地址空间中,无须底层提供复杂的内存管理、特权集隔离。该结构中,应用程序对操作系统服务的调用可直接通过函数调用高效完成,但是缺点就是任何一个应用或操作系统模块出现了问题,则可能导致整个系统崩溃。MS-DOS 就是典型代表。
简要结构的操作系统主要运行在微控制单元(MicroController Unit,MCU)等相对简单的硬件上,这些硬件没有提供现代意义上的内存管理单元(MMU),隔离能力较弱或缺失,难以运行复杂的操作系统。
- 宏内核(Monolithic Kernel)
- 又称单内核,其特征是操作系统内核的所有模块(包括进程调度、内存管理、文件系统、设备驱动等)均运行在内核态,具备直接操作硬件的能力。典型代表是 UNIX/Linux、FreeBSD 等。
- 微内核(MicroKernel)
- 弹性扩展能力:对于一个宏内核来说,很难仅仅通过简单的裁剪或扩展使其支持资源诉求从 KB 到 TB 级别的场景。
- 硬件异构性:异构硬件往往需要一些定制化的方式来解决特定问题,这种定制化对于宏内核来说很难得到长期的支持。
- 功能安全:由于宏内核在故障隔离和时延控制等方面的缺陷,截止目前尚无通过高等级功能安全认证的先例。
- 信息安全:内核态驱动容易导致低质量的驱动代码入侵内核,粗粒度权限管理容易带来权限漏洞等。
- 确定性时延:宏内核资源隔离较为困难,且各模块耦合度高导致难以控制系统调用的时延,因此难做到确定性时延,即便为时延做一些特性的优化,时延抖动仍然较大。
- 服务与服务之间是完全隔离的,单个服务即使出现故障或受到安全攻击,也不会导致整个系统崩溃,从而有效提高操作系统的可靠性和安全性。
- 微内核可以更方便地不同场景定制不同的服务,从而更好地适用于不同的应用需求。
- Motivation:由于在宏内核架构下,所有内核模块都运行在特权空间。所以当宏内核操作系统的内核功能不断增长的时候,系统的复杂度也持续增加,在可靠性和安全性等方面都带来更多的问题,一个单点的错误就可能导致整个系统崩溃。
- 将单个功能或模块(如文件系统、设备驱动等)从内核中拆分出来,作为一个独立的服务部署到独立的运行环境中,内核仅保留极少的功能,为这些服务提供通信等基础能力,使其能够互相协作以完成操作系统所必须的功能。
- 微内核的优点
- VS 宏内核
- 外核(Exokernel)
- Motivation:内核在硬件管理方面的两个主要功能是资源抽象与多路复用。而在资源的抽象上存在两方面的问题:1.过度的硬件资源抽象可能会带来较大的性能损失,违反“抽象但不隐藏能力”原则;2.操作系统提供的硬件资源抽象是针对所有应用的通用抽象,这些抽象对一些具体的应用(如数据库、Web服务器)来说往往不是最优的选择。
- 1995 年 MIT 提出了外核架构。他们发现应用比操作系统更了解该如何去抽象和使用硬件资源,他们提出应该由应用来尽可能地控制对硬件资源的抽象,同时提出了库操作系统(LibOS)的概念,将硬件的抽象封装到 LibOS 中,与应用直接链接,降低应用开发的复杂度,而内核则只负责对硬件资源在多个 LibOS 之间的多路复用的支持,并管理这些 LibOS 的生命周期。
- 外核架构可以为不同的应用提供定制化的高效资源管理:按照不同应用领域的要求,将硬件资源抽象模块化为一系列的库(即LibOS)。这样有两个好处:1.可按照应用领域的特点与需求,动态组装成最适合该领域的 LibOS,最小化非必要的代码,从而获得高性能。2.处于硬件特权级的内核可以做到非常小,并且由于多个 LibOS 之间的强隔离性,所以整个计算机系统的安全性和可靠性都得到了提升。
一些功能受限、对操作系统接口要求不高但对性能和时延特别敏感的嵌入式场景中,就会通过 LibOS 来运行应用业务。此外,云计算平台中的容器架构很多也都采用了脱胎于外核架构的 Unikernel(相当于 LibOS 的实现),而虚拟机监控器则作为支撑 Unikernel 运行的内核。- 外核架构的劣势在于:1.LibOS 是为某种应用定制的,缺乏跨场景的通用性,应用生态差。很难用于功能要求复杂、生态与接口丰富的场景,因为这意味着要将 LibOS 做得特别复杂,甚至相当于一个完整的宏内核,从而丧失了外核架构带来的性能、安全等优势。2.不同 LibOS 通常会实现相同或类似的功能,容易造成代码冗余。因此,对于资源受限的场景,通常需要一些跨地址空间的代码去重或共享机制来减少内存开销。- VS 微内核
代码语言:javascript复制 - 外核是将多个硬件资源切分成一个个切片,每个切片中保护的多个硬件资源由 LibOS 管理并直接服务与一个应用;而微内核架构则是通过让一个操作系统模块独立运行在一个地址空间上来管理一个具体的硬件资源,为操作系统中的所有应用服务。
- 外核的内核主要是为 LibOS 提供硬件的多路复用能力并管理 LibOS;而微内核中,内核主要提供进程间通信功能。
- 外核架构在面向一个功能与生态受限的场景时可通过定制化的 LibOS 获得高性能;微内核架构则需要更复杂的优化才能获得与之相当的性能。
- 多核(Multikernel)
- Motivation:当前的硬件结构呈现两个主要特性:1.多核乃至众核(8 个及以下处理器称为多核,多于 8 个处理器核称为众核)的流行使得一个服务器中通常存在成百上千个处理器核 2.Dennard 缩微定律的终结以及应用需求的多样化使得处理器走向异构化,甚至是动态异构化,也就是一个处理器上可能集成多种功能、性能甚至指令集架构各异的处理器核。
- 基于硬件的众核与异构特性,Multikernel 的想法是将一个众核系统看成一个由多个独立处理器核通过网络互联而成的分布式系统。与传统的操作系统类似,Multikernel 仍然假设硬件处理器提供全局共享内存的语义,但对于不同处理器核之间的交互,它提供了一层基于进程间通信的抽象,从而避免了处理器核之间通过共享内存进行隐式的共享。
Multikernel 在每个 CPU 核上运行一个独立的操作系统节点,节点间的交互由操作系统解节点之上的进程间通信来完成。- 好处是:通过这种架构,Multikernel 可以避免传统操作系统架构中的复杂的隐式共享所带来的性能可扩展性瓶颈,并且由于不同处理器核上的操作系统节点是独立的而且可以是不同的,从而非常容易支持异构处理器架构。
不足之处是:不同节点之间存在的状态冗余对资源开销会造成一定压力,上层的应用必须使用 Multikernel 提供的进程间通信接口才能进行交互,绝对性能方面不一定存在优势,且需要移植现有应用才能适应 Multikernel。
- 混合类型
- Linux 是公认的宏内核架构,但近期也开始融合了微内核架构中的用户态驱动模型。
- 苹果操作系统内核 XNU 是一个 Mach 微内核 BSD Linux 的混合体,被用于 MacOSX 中。
- Windows NT 的操作系统内核也采用了微内核设计思想,但是将一些系统服务运行在内核态。
操作系统框架结构
Android
- 硬件抽象层(Hardware abstart layer)
- Android 在 Linux 内核之上提供了一层硬件抽象层。提供这层的主要原因是:
- Linux 宏内核架构属性使得设备驱动通常运行在 Linux 内核态,因此设备驱动的接口依赖于 Linux 内核设备驱动接口的演进,从而与某个 Linux 内核版本的实现产生耦合,这会阻碍 Android 系统框架的独立演进与升级。简单来说,就是假如还使用 Linux 内核提供的设备驱动的话,那么会受限于 Linux 内核,Android 并不想要使用 Linux 内核。
2.Linux 内核采用 GPL v2 开源协议,协议要求运行在同一地址空间的设备驱动必须开放源码,这会导致一些硬件的实现细节也被公开,一些设备厂商担心其硬件竞争力受到影响。
因此,Android 提供了硬件抽象层,在这一层封装了一些硬件实现的细节,从而更好地实现 Linux 内核与 Android 系统框架的解耦;并通过提供用户态驱动模型,使得设备厂商不需要开放源代码就能为 Android 操作系统提供设备驱动,从而促使更多的设备厂商加入 Android 生态。
个人理解就是:Android 并没有使用 Linux 内核提供的硬件抽象、驱动等,而是定义了一套自己的一套硬件抽象,从而可以更好地支持设备等。
- Android 自定义库(Android Library)
- 1.提供一些方便 Android 应用开发的自定义库;2.重新定义了一些标准库(如 glibc 等),从而规避了 LGPL 协议。
- Android 运行环境(Android Runtime,ART)
- 1.由于 Android 应用的主要开发语 言是 Java,而 Java 程序的运行需要一个虚拟机,所以这一层主要就是为 Java 程序的运行提供支持。
Android 早期的时候采用 Dalvik 虚拟机的形式,通过解析执行与 JIT(Just In Time)编译的方式运行,这带来一些性能与功耗的损失;
Android 自 5.0 后引入了 Android 运行环境(ART),通过 AOT(Ahead-of-Time)预先编译的方式,将 Java 代码预编译为二进制可执行代码,从而避免了运行时的编译开销。
- Android 应用框架(Android application framework)
- 提供应用运行时所需要的基础服务,包括服务管理、活动管理、包管理、窗口管理等。这些服务化的组件利用操作系统内核提供的资源抽象,为应用构建了一系列方便调用的应用服务。
个人理解就是:编写 Android 程序其实就是在 Android 这个框架下编写自己的应用逻辑代码来利用这个框架提供的一些服务等,所以这一层就相当 Android 框架,类似与 Spring 这些的。