内核 :操作系统管理硬件和资源的核心组件

更新时间:2024-09-20 22:08

内核(Kernel)是操作系统中最重要的组件之一,它直接运行在硬件之上,负责提供内存管理、进程管理、设备管理、文件管理系统、网络通信、系统调用与同步等基础服务。主流内核架构可以分为宏内核(Monolithickernel)、微内核(Microkernel)、多内核(Multikernel)、混合内核(Hybridkernel)和外核(Exokernel)以及纳米内核(Nanokernel)等。

操作系统内核的发展历程始于无内核时代,程序直接在硬件上运行,没有统一的资源管理和调度机制,也缺乏对硬件资源的抽象和管理。20世纪60年代,CTSS和Multics等分时操作系统引入宏内核,实现多用户和多任务处理。1969年,微内核架构(如Mach和L4)将功能分解为独立组件,提升性能和安全性。1995年,外核架构允许应用程序直接管理硬件,提高性能和定制性。2009年,多内核架构被提出,通过将众核系统视为由多个独立处理器核组成的分布式系统,使用进程间通信代替共享内存交互,提升性能和扩展性。大多数内核是为特定操作系统开发的,通常每个操作系统只有一个内核版本,Microsoft Windows 2000和Windows 98各有独特的内核。相比之下,Linux内核更具灵活性,拥有多个版本,可以由用户进行多种方式的修改。少数内核则设计为与任何操作系统兼容。Mac OS使用基于Unix的XNU内核,结合了结合了微内核和宏内核的优势。

在保护与安全机制方面,内核通过内存保护、特权级别、进程隔离和访问控制等技术,确保系统的稳定性和安全性。内核模式与用户模式的分离使得系统调用时能够有效管理权限,防止恶意代码对系统核心的破坏。

发展历程

无内核时代

1945年到20世纪50年代中期,处于发展早期的计算机是以硬件为主导的。程序员直接在硬件上编写程序,由程序控制着计算机的所有操作。每个程序都是为特定硬件设计的,没有通用性可言,在不同程序之间执行会进行重置和重新加载。随着计算机技术的发展,出现了批处理系统,这些系统允许用户一次提交一批作业,由计算机依次执行,但这些系统并没有像现代操作系统那样提供资源管理和多任务处理的功能。

宏内核架构的提出

1960年代,随着分时操作系统的出现,内核开始成为操作系统的核心组件。分时操作系统允许多个用户通过终端访问计算机系统,实现了多任务处理和资源共享。早期的分时操作系统,如多用户多任务操作系统Multics(Multiplexed Information and Computing Service),具有单一的内核,负责管理系统资源和提供基本的系统调用接口。这些早期的操作系统内核通常被称为宏内核,所有的核心功能都作为一个单一的、运行在内核态的大型程序。

随着宏内核操作系统的内核功能不断增长,系统的复杂度也持续增加,宏内核架构下,所有内核模块均运行在特权空间,一个单点的错误就可能会导致整个系统崩溃或者被攻破,计算机系统的可靠性、安全性等方面开始出现问题。为此,研究人员开始尝试对宏内核架构的操作系统进行解耦,将操作系统的核心功能分解成最小的、独立的组件,在一个最小的特权级别上运行的内核——即微内核。

微内核架构的提出

1969年,由佩尔·布林奇·汉森教授(Per Brinch Hansen)开发的RC 4000多路编程系统是微内核架构操作系统的雏形,该系统将操作系统组件分离为相互交互的功能组件及一个负责消息通信的内核。1975年,罗彻斯特大学开发了Aleph操作系统内核。1979年,Aleph内核的主要设计者理查德·拉希德(Richard Rashid)加入卡耐基·梅隆大学,并于1981至1985年间参与开发了Accent内核。1985至1994年间,卡耐基梅隆大学开发了MACH内核,作为第一代微内核的代表。Mach以进程间通信(IPC)作为所有系统服务与内核交换数据的基础机制,通过利用IPC、虚拟内存和多进程等特性,将冗余的系统服务移出内核并作为进程运行。但Mach对进程间通信(Inter-Process 传播学)的设计过于通用加上Mach微内核自身资源(包括内存与CPU缓存等)占用过大的问题使得其性能与同时期的宏内核相比存在差距。

1993年,乔亨·利特克教授(Jochen Liedtke)指出,高性能IPC的设计与实现必然是与体系结构相关的,过度抽象将极大影响IPC的性能,而利用体系结构相关的状态进行优化则可将IPC性能提升到极致。为此乔亨·利特克设计并实现了L4微内核系统并提出了微内核的最小化原则,即一个操作系统内核的功能只有在将其放在内核态以外会影响整个系统的功能时,才能被放置在内核态。通过高性能的IPC实现以及极小化的微核(即微内核系统的内核态部分,又称kemel),微内核架构操作系统的性能可以达到甚至超过同时期的宏内核架构操作系统。L4被认为是第二代微内核操作系统的代表。

外核架构的提出

操作系统内核在硬件管理方面的两个主要功能是资源抽象与多路复用(Multiplexing)。在实际操作中,对硬件资源的抽象存在一些问题(包括过度的硬件资源抽象可能会带来较大的性能损失等问题),这催生了新的架构思想。1995年,MIT的道森·英格勒教授(Dawson R. Engler)和弗朗斯·卡肖克教授(M. Frans Kaashoek)及詹姆斯·奥图尔(James O’Toole Jr)提出了外核架构。外核架构可为不同的应用提供定制化的高效资源管理:按照不同应用领域的要求,将对硬件资源的抽象模块化为一系列的库(即LibOS)。

微内核的安全性增强

1999年,乔纳森·夏普罗(Jonathan S. Shapiro),乔纳森·史密斯(Jonathan M. Smith),以及大卫·法伯教授(David J. Farber)在的论文中提出了EROS,首次将能力(Capabllity)机制引入微内核操作系统中,并高效地实现了该机制,微内核的安全性在此阶段进行进—步增强。seL4是一个典型的基于Capability机制的微内核,并引入形式化证明方法,通过数学的方式证明了其微核部分满足从设计到实现的—致性,以及微核上的服务具有互不干扰等属性。安全性的增强成为第三代微内核架构操作系统的重要特征。

多内核架构的提出

21世纪初期,随着多核乃至众核架构在服务器和个人计算平台上的普及,一个服务器或计算机中通常存在着成百上千个处理器核心,传统的共享内存模型在大规模并行处理和多核架构中往往面临着性能瓶颈和可扩展性限制。其次Dennard缩微定律的终结以及应用需求的多样化使得处理器走向异构化,即处理器核心可能集成多种不同功能、性能和指令集结构。为此,操作系统的内核架构开始针对异构众核等问题发展出新的方向。

2009年,苏黎世联邦理工学院计算机系统研究所、微软研究院、雷恩高等学校于提出了多内核架构,基本理念是将—个众核系统看成一个由多个独立处理器核通过网络互联而成的分布式系统,并提供了—层基于进程间通信的抽象来实现不同处理器核之间的交互,避免了处理器核之间通过共享内存进行隐式的共享。其中Barrelfish是一个特定的多内核操作系统实现。例如,王振宁教授等人提出了“同时多内核”(Simultaneous Multikernel, SMK)设计。这种设计允许在每个流多处理器(SM)中并行执行多个内核,从而提高资源的使用效率。SMK利用细粒度的上下文切换机制,使得单个SM能够同时处理多个内核任务,极大地增强了系统的处理能力。

功能

内存管理

为了确保应用程序能够高效且安全地共享物理内存资源,操作系统内核引入了虚拟内存这一重要抽象概念。内核不仅管理应用程序与物理内存之间的映射关系,还负责物理内存的动态分配与释放。

虚拟内存管理:现代操作系统广泛采用基于分页机制的虚拟内存设计与实现,内核通过页表来管理进程的虚拟地址空间和物理地址空间之间的映射关系,每个进程都有自己的页表,内核负责维护和更新这些页表。当系统的可用物理页不足时,内核会根据设定的页替换策略,选择将一些物理页移出到磁盘,释放空间以满足当前的内存需求。

物理内存分配:在提供虚拟内存抽象的同时,内核仍然需要把真实的物理内存分配给每个应用程序,操作系统内核采用多种策略来优化物理内存的使用,其中包括伙伴系统和SLAB分配器等。其中伙伴系统被广泛地用于分配连续的物理内存页,其基本思想是将物理内存划分成连续的块,以块作为基本单位进行分配。不同块的大小可以不同,但每个块都由—个或多个连续的物理页组成。

进程管理

为了管理程序的运行,操作系统提出了进程(Process)的抽象:每个进程都对应于—个运行中的程序。内核提供了相应的进程创建与销毁、进程调度、进程上下文切换等服务。

在不同的操作系统中,内核的实现和提供的服务可能有所不同。例如,在Windows操作系统中,进程的核心机制如进程调度是在微内核中实现的,而进程的创建和状态管理则在执行体中进行(如PspCreateProcess内核函数完成进程的创建等)。相比之下,在UNIX系统中,进程控制、进程通信以及进程调度等功能都是由内核的进程控制子系统来实现的。unix的内核为用户提供了一系列控制进程的系统调用,包括创建新进程的fork调用;实现进程终止的exit调用;改变进程执行代码的exec调用;以及使调用进程挂起等待子进程终止的wait调用等。

设备管理

设备驱动程序是用于控制外部设备的软件模块,以实现对外部设备的管理,使应用程序可以通过系统调用的形式来操纵和使用外部设备。由于设备种类的增多,为了解决设备多样性的问题,现代操作系统内核提供了设备驱动模型这一抽象,即事先规定好—组数据结构和应该实现的接口,然后驱动开发人员将设备驱动的开发转化为对数据结构的填充以及接口函数的挂载以简化新驱动的开发与维护。

Linux将设备驱动程序作为独立的内核模块,仅在检测到设备时才动态加载,并在移除设备时卸载。其设备驱动模型定义了设备、驱动、总线和类四种抽象,使用kobject统一管理。kobject是设备驱动模型的基类,通过层次结构和引用计数机制进行管理和释放。

文件管理系统

操作系统内核提供了文件系统这一抽象,为上层应用程序提供文件抽象并实现文件访问所需要的接口,以特定格式在存储设备上维护着每个文件的数据和元数据。因此文件系统的设计需要实现两个方面的任务,第一个是定义文件系统对用户的接口。这个任务涉及定义文件及其属性、文件所允许的操作、组织文件的目录结构。第二个任务是创建数据结构和算法来将逻辑文件系统映射到物理外存设备上。

文件系统通常采用分层式的设计方式,每一层的功能模块为上一层提供服务。其中I/O控制为最底层,由设备驱动程序和中断处理程序组成,实现内存与磁盘之间的信息传输。基本文件系统只需要向合适的设备驱动程序发送一般命令就可对磁盘上的物理块进行读写。文件组织模块对文件的逻辑块与物理块的管理,负责逻辑地址到物理地址的映射。逻辑文件系统管理元数据(包括文件系统的所有结构数据),通过文件控制块来维护文件结构。

网络通信

内核中的网络功能主要由三个子模块构成:Socket、协议驱动和网络设备驱动。首先,Socket作为操作系统内核向用户程序提供的通信接口,用于建立用户程序之间的网络连接。一个 socket 包含协议、本地地址、本地端口、远程地址和远程端口等信息,确保通信的准确性和稳定性。接着,协议驱动程序负责将高层的网络API请求转换为底层的网络协议请求,实现了OSI七层模型中的传输层和网络层功能。这包括对TCP、UDP等网络协议的处理。协议层在数据包从网络设备驱动传递到socket接口或从socket接口传递到网络设备驱动的过程中,对数据包进行各种处理操作,如改写、新建、分割成帧、重新组装或丢弃不必要的数据包。最后,网络设备驱动则负责在内核和网络硬件之间传递数据包,确保数据在软硬件之间的高效传输。这三个子模块相互协作,共同完成内核中的网络通信功能。

系统调用

操作系统内核设置了一组用于实现各种系统功能的子程序(过程),并将它们提供给应用程序调用。由于这些程序或过程是内核的组成部分,为了保护操作系统内核不被用户程序破坏,一般都不允许用户程序访问操作系统的程序和数据,所以也不允许应用程序采用一般的过程调用方式来直接调用这些过程,因此内核向应用程序提供了一系列的系统调用命令,让应用程序通过系统调用去调用所需的系统过程。

系统调用的实现:当应用程序使用内核所提供的系统调用时,产生一条相应的指令,CPU在执行这条指令时发生中断,并将有关信号送给内核,由内核启动相关的中断与陷入处理程序进行处理,实现该系统调用所需要的功能。具体过程如下,陷入到内核态之后,由硬件和内核来完成被中断进程的CPU环境的保护,将程序计数器PC、系统调用号、及寄存器内容等压入堆栈。其次是内核根据系统调用号去查找系统调用入口表,找到系统调用处理子程序入口地址而转去执行它。

同步

在多任务操作系统中,不同的程序会向内核提出各种系统调用请求,这些请求并不总是严格按顺序执行,而是可以交错进行。因此,多个程序可能会同时竞争访问同一共享资源,从而引发竞争条件。为了管理这种竞争并确保系统的稳定性和安全性,内核会采用恰当的同步机制来控制并协调这些请求。常见的同步原语有互斥锁、信号量等。

互斥锁(mutexlock):利用硬件保证的原子操作内核可以实现互斥锁夹解决临界区问题,确保在任一时刻只有一个线程可以拥有锁。当线程进入临界区前,它必须先获得互斥锁;只有获得锁的线程才能执行临界区内的代码。线程在完成临界区的任务后会释放锁,从而允许其他线程获取锁并进入临界区。

信号量:临界资源的数量可以以信号量的数量指代,信号量的数值代表临界资源的数量,并通过wait(S)或signal(S)这对原子操作来实现信号数值的加一或减一,即每次获得或释放一个单位的临界资源。通过信号量机制,内核可以实现进程的同步与互斥。

结构设计方法

模块化

模块化程序设计技术是20世纪60年代出现的一种结构化程序设计技术。该技术是基于“分解”和“模块化”原则来控制大型软件的复杂度。这种方法将操作系统内核划分为独立的功能模块,每个模块负责特定的任务,并通过明确定义的接口来实现模块之间的交互和通信。例如,一个常见的模块化结构包括进程管理模块、内存管理模块、文件系统模块、设备驱动程序模块以及网络协议栈模块。每个模块都有自己的责任范围,比如进程管理模块负责管理系统中的进程,包括进程的创建、调度和销毁;内存管理模块负责管理系统的内存资源,包括内存分配、释放和地址映射等。

这些模块通过定义清晰的接口来相互交互,这样可以降低内核的复杂度,提高内核的可维护性和可扩展性。

分层

分层是一种通过抽象级别来控制系统复杂性的方法。它将一个大系统分解为一系列模块,每个模块都有明确的功能和接口,并按照一定的层次进行组织。分层设计的核心在于约束模块之间的交互方式,从而减少模块之间的耦合性。通常的原则是,一个模块只能与同层模块以及相邻的上层或下层模块进行交互,而不能跨层次进行交互。这种结构自下而上地进行设计,使得所有设计决策都是有序和可靠的。分层结构自下而上的设计方式,使所有设计中的决定都是有序的,或者说是建立在较为可靠的基础上的,保证整个系统的正确性;在不改变层次间接口的情况下,可以增加、修改或替换某一层次中的模块或整个层次,而不会影响其他层次,便于系统维护和扩展。

层级

层级设计是一种通过功能关联性和递归组合来管理模块的方法。首先,将功能相近的模块组成一个具有清晰接口的自包含子系统,然后再将这些子系统递归地组合成更大的子系统。例如,虚拟内存是一个子模块,与物理内存分配、缺页异常处理、页换入换出等一起构成内存管理模块,内存管理模块再与进程管理模块、设备驱动模块等一起构成操作系统内核。层级设计通过将功能相近的模块组合在一起,使得子系统具有高内聚性;通过递归组合子系统,形成更大、更复杂的系统。

分类

宏内核

宏内核(Monolithic kernel)是一种将操作系统的主要功能集中在内核空间中运行的设计,包括处理器调度、内存管理、文件系统和设备驱动程序等核心功能。这种结构在硬件之上定义了高阶的抽象接口,并通过一系列系统调用来实现操作系统的功能。在宏内核中,各功能模块虽运行在核心态,但是高度集成,使得内核代码编写和维护具有一定难度。一个小错误可能导致整个系统崩溃。

尽管存在这些挑战,宏内核由于所有低级操作都在同一个地址空间中实现,因此在效率上通常优于在多个地址空间中运行的设计。许多现代宏内核,如LinuxFreeBSD,支持运行时动态加载模块,这不仅简化了内核的核心部分,还便于扩展内核功能。宏内核的设计尽管复杂,但其集成度高和运行效率的优势使其在许多系统中得到应用,特别是在需要高性能和高稳定性的环境下。此外,它的结构趋向于更易于正确设计和快速发展,与微内核相比,宏内核的发展速度更快。

微内核

微内核(Microkernel)结构特征是一个最小的硬件抽象层,包含了建立系统所需的核心原语或系统调用,如基础的内存管理、进程间通信和进程同步。这种架构使得许多操作系统组件,如进程和设备管理,在内核外以较低的系统访问级别运行。

微内核设计遵循“机制与策略分离”原则,将基本机制集中在内核的低层,而将具体策略置于较高层次。通过这种方式,诸如文件系统和设备驱动等功能模块被拆分成独立服务,并部署在独立的用户态服务器中,仅保留通信等基础能力在内核中。这样的分离不仅简化了内核的核心设计,也提高了操作系统的可靠性和安全性,因为单个服务组件的故障或安全问题不会影响整个系统。例如L4微内核系列和Mach(用于GNU Hurd和Mac OS),通过模块化设计实现高度的可靠性和安全性。

多内核

多内核(Multikernel)操作系统将系统构建为一个由多个核心组成的分布式系统,这些核心之间通过显式消息传递进行通信,并且不共享内存。在每个CPU核上运行一个独立的操作系统节点,节点间的交互由进程间通信来完成。通过这种架构,多内核避免了传统操作系统架构中的隐式共享所带来的性能瓶颈,并支持异构处理器架构。

多内核模型的设计基于几个关键原则:显式的核间通信,核心之间的通信通过显式消息传递,而不是共享内存,提高了系统透明性;操作系统结构与硬件独立,操作系统的结构尽可能与硬件无关,以适应不同的硬件配置;将状态视为复制而非共享,系统中的状态在各个核心之间复制,而不是共享,简化了同步,避免了共享内存体系结构的复杂性。其中,Barrelfish是一个研究性操作系统,由苏黎世联邦理工学院微软研究院和雷恩高等师范学校设计,专为多核和分布式系统优化。它采用轻量级内核设计,每个核心运行独立的监视器协调通信,大部分系统服务在用户空间运行。

混合内核

混合内核结合了宏内核和微内核的特点,保留宏内核的高性能和低延迟优势,同时借鉴微内核的结构模块化和可维护性。与微内核相比,混合内核中的所有(或几乎所有)操作系统服务仍然位于内核空间中,这意味着没有像微内核那样将服务放在用户空间带来的可靠性优势,但也避免了微内核在内核和用户模式之间进行消息传递和上下文切换带来的性能开销。

现实中的操作系统常融合多种架构设计思想。例如,Linux内核被认为是宏内核,但也开始融合微内核架构的用户态驱动模型。苹果公司的XNU内核是Mach微内核与BSD UNIX的混合体,用于Mac OS。Windows NT内核也采用了微内核设计思想,但将一些系统服务运行在内核态。

外核

外核(Exokernel)不同于传统操作系统,它将资源管理和保护分离,允许应用程序通过库操作系统(LibOS)自定义、扩展或替换操作系统抽象。外核的设计目标是将资源的保护与管理分离,从而允许应用程序更灵活地管理和控制硬件资源,提高性能和可定制性。外核通过分离资源的保护和管理,只提供基本的保护功能(如分配、撤销、共享和所有权跟踪),而具体管理策略由应用程序决定;直接暴露硬件资源,让应用程序灵活控制特权指令和物理内存;采用细粒度保护,提升资源管理效率。

当前有很多领域已经使用了外核架构,在一些对操作系统接口要求不高但对性能和时延敏感的嵌入式场景中,通过LibOS运行应用业务,将数据面与控制面分离;在云计算平台的容器架构中,采用Unikernel支持高性能业务的独立部署。

纳米内核

纳米内核是一种极简化的操作系统内核,旨在提供最小化但必要的核心功能以支持操作系统的运行。与传统内核相比,纳米内核仅包括基本的调度、内存管理和进程间通信(IPC)功能,其它操作系统功能如设备驱动、文件系统和网络协议等则在用户空间实现。这种设计理念源于追求系统的高可靠性、安全性和灵活性。

纳米内核的设计基于无状态内核、单级存储和能力机制这三大原则,无状态内核确保不在内核中保存关键状态,单级存储模型确保所有数据持久存在于虚拟内存中,能力机制通过密钥实现对对象的唯一引用和访问控制,从而提高了系统的速度、可靠性和安全性。这些原则使KeyKOS纳米内核高效、安全、可靠,能够支持复杂的多用户环境。尽管纳米内核的概念源于学术研究,但其在实际应用中也获得了广泛关注和采用。例如,现代微内核架构的操作系统如QNXMINIX和L4,都在不同程度上实现了纳米内核的设计理念。这些系统在嵌入式设备、实时系统和安全关键系统中表现出色,证明了纳米内核架构的优势。

主流操作系统内核架构

Linux

Linux内核子系统主要分为三个主要部件,I/O部件、内存管理部件、进程管理部件。

Linux内核架构

Linux中的I/O组件负责与设备的交互及联网和存储功能,主要通过虚拟文件系统层进行整合。无论是读内存中的文件还是从终端读取字符,顶层处理方式相同。底层则依赖具体的设备驱动程序,包括字符驱动程序和块驱动程序。字符设备支持即时和行编辑模式,如终端和编辑器。网络层面,Linux支持模块化设计,通过协议栈和socket接口处理数据包,确保网络通信的效率。磁盘I/O则通过调度器优化读写操作,减少无效磁头移动。文件系统位于块设备的顶层,提供硬件抽象,允许多个文件系统并存。

Linux的内存管理分为物理内存管理和虚拟内存管理两部分。物理内存被划分为不同区域,每个区域都有自己的页面分配程序,负责管理物理页面的分配和释放。虚拟内存系统负责每个进程的虚拟地址空间,管理页面的创建、加载和交换。系统通过vm_面积_struct结构描述每个内存区域的属性,如保护模式和共享状态。

Linux的进程管理包括进程的创建、销毁及调度。进程以task_struct结构表示,包含进程的标识符和控制信息。Linux使用基于优先级的抢占式调度算法,维护两个优先级队列来管理任务的执行。任务通过运行队列管理,调度器选择最高优先级的任务执行,并在时间片耗尽时交换优先级队列。

Linux内核优缺点

Linux内核以其开放源代码、高度可定制化、广泛的硬件支持和强大的网络功能而闻名。它支持多种处理器架构,并且具有良好的性能和稳定性记录。Linux内核的模块化设计使得用户可以根据需求添加或移除功能。对于不熟悉Linux内核的用户而言,其学习曲线较陡峭,软件兼容性较低,包括某些专有软件及大多数游戏。此外,尽管Linux拥有可靠的在线社区和丰富的文档,但专门的技术支持较难找到。

Windows

Windows NT是由微软于1933年所推出的纯32位操作系统核心,是目前Windows主流操作系统版本的基础,包括Windows 7(对应的NT版本为NT 6.1)、Windows 10Windows 11(对应的NT版本为NT 10.0)。

Windows内核架构

Windows操作系统主要分为用户模式(user mode)和内核模式(kernel mode)。用户模式运行的是一般的应用程序,而内核模式运行的是操作系统内核以及设备驱动程序等,内核模式主要包括Windows执行体、Windows内核、设备驱动程序、硬件抽象层(HAL)。

Windows执行体提供基础操作系统服务,包括内存管理、进程和线程管理、I/O管理、缓存管理和网络通信。主要组件有配置管理器(管理系统注册表)、进程管理器(创建和终止进程及线程)、I/O管理器(分派I/O请求)、缓存管理器(提高文件I/O性能)和内存管理器(实现虚拟内存)。

内核提供低级操作系统机制,主要关注线程调度和分派,使用处理器控制区域(KPCR)和控制块(KPRCB)存储处理器特定数据。KPCR包含中断分派表、任务状态段和全局描述符表,KPRCB包含调度信息、DPC队列和CPU统计数据。

设备驱动程序是内核模式模块,包括硬件设备驱动程序(使用HAL与物理设备交互)、文件系统驱动程序(转换文件I/O请求)和协议驱动程序(实现网络协议)。

HAL处理与硬件相关的操作,如中断处理和多处理器通信,提供硬件抽象,使Windows能在不同硬件平台上运行,简化驱动程序开发,增强系统稳定性和兼容性。

Windows内核优缺点

Windows内核具有较高的可移植性和可扩展性。它依赖HAL接口而非直接硬件,采用分层结构,在内核模式下提供系统服务,用户模式的子系统模拟不同操作系统。I/O系统支持可加载驱动程序,便于扩展新文件系统、I/O设备和网络。但Windows内核架构复杂,涉及多个子系统和组件,这使得其开发、维护和调试变得困难;尽管HAL提供了硬件抽象层以提高兼容性,但也带来了一些额外的复杂性和性能开销。

macOS

macOS内核称为XNU,它由三个主要组件组成:MACH、BSD和I/O Kit。

macOS内核架构

Mach是XNU内核的核心,起源于卡耐基·梅隆大学开发的Mach 3.0。它提供硬件抽象、处理器管理(包括对称多处理和调度)、虚拟内存管理(包括低级分页、内存保护、共享和继承)、抢占式多任务处理、内核调试支持和控制台输入输出。Mach通过IPC机制实现内核间消息传递服务,支持客户端/服务器模式,其中任务通过端口与其他任务通信,端口控制访问权限。

BSD层位于Mach与用户应用程序之间,利用Mach提供的服务实现操作系统功能。在OS X中以特权模式运行,与Mach和i/o Kit共享地址空间。BSD层衍生自FreeBSD 5,提供进程管理、内存管理、文件系统、驱动程序和系统调用等服务。

I/O Kit是面向对象的框架,用于编写设备驱动程序和其他内核扩展,提供对系统硬件的抽象,支持代码重用和新驱动程序开发。

macOS内核优缺点

Mach、BSD和I/O Kit组件之间的明确分离减少了维护成本,促进了代码的清晰性。Mach消息API提供了强大的消息传递功能,特别适用于用户模式应用程序;KEXT缓存优化了启动时间,增强了系统性能;Fat/universal二进制文件允许单个安装CD或HDD在不同的CPU架构上运行,避免了重复文件或目录的混乱。但封闭的生态系统限制了用户和开发者的自定义能力,第三方硬件支持较少,且对旧硬件的兼容性较差。

保护与安全机制

内核为用户程序提供基础服务,分配和管理计算机系统资源,内核代码的执行拥有所有权限,并可以访问系统中任何有效的内存地址,因此需要将内核程序与用户程序进行隔离,避免内核受到来自用户态程序的意外破坏、不良行为的篡改或者恶意代码的破坏。为了防止恶意用户程序干扰内核程序的运行,内核需要实现一定的安全与保护机制,包括访问控制及权限管理。

常见内核漏洞

一个静态的、未初始化的指针有一个NULL(0x0)值,并且NULL又常常是表示内存分配失败的返回值。如果内核路径想要取一个NULL指针的值的时候,就相当于是使用内存地址0x0,而这会导致严重错误,因为该地址一般不会放置任何东西。

通常由越界写入造成的,比如使用不安全的C函数,如strcpy()或sprintf()。这两个函数都是向目标缓冲区写入内容直到遇到\0结束符,而不检查写入了多少。不正确的循环结束条件也会造成内核栈漏洞,例如需要为数组赋值且发生数组越界时,可能会重写敏感的内存区域。

通常导致缓冲区溢出的原因包括使用不安全的函数、未正确终止的循环以及对安全函数的错误使用。这种情况可能导致内核内存的随机部分被覆写、与缓存相关的元数据被覆写,以及跟在溢出块后面的块被覆写等后果。

访问控制及权限管理

内核通过访问控制和权限管理,确保资源的安全和系统的稳定性。访问控制技术可以实现对用户程序对系统资源的范围限制、对系统资源的访问权限等等。这些系统资源包括各类硬件对象(如 CPU、存储器、终端、磁盘驱动器和打印机等)、软件对象(如程序、文件、数据结构和信号量等)。

访问矩阵(Access Matrix)可以用来描述系统的访问控制,访问矩阵中的行代表域,列代表对象,矩阵中的每一项是由一组访问权组成的。例如图中的控制矩阵,它是由三个域和8个对象所组成的。当进程在域D1中运行时,它能读文件F1、读和写文件F2。进程在域D2中运行时,它能读文件F3、F4和F5,以及写文件F4、F5和执行文件F4,此外还可以使用打印机1。只有当进程在域D3中运行时,才可使用绘图仪2。

访问矩阵可以按列划分,或者按行划分,以分别形成访问控制表或访问权力表:

访问控制表(Access Control List),是将访问矩阵按列(对象)划分,每个对象的列表由一有序对(域,权集)所组成。

访问权限表(Capabilities),是将访问矩阵按行(域)划分,由一个域对每一个对象可以执行的一组操作所构成的表,表中的每一项即为该域对某对象的访问权限。当域为用户(进程)、对象为文件时,访问权限表便可用来描述一个用户(进程)对每一个文件所能执行的一组操作。

内核与硬件交互

中断处理

中断处理是内核与硬件交互的核心机制之一,用于处理来自硬件设备的异步事件。硬件设备通过中断请求信号通知CPU发生事件,CPU根据中断号在中断向量表中查找并执行对应的中断处理程序,该程序会保存当前执行状态,处理中断事件,如完成I/O操作、处理键盘输入等。处理完成后,CPU恢复中断前的状态,继续执行被中断的程序。

系统启动

系统启动是操作系统加载和初始化的过程。计算机开机时,BIOS/UEFI固件执行电源自检,检查硬件状态。然后,BIOS/UEFI加载引导扇区(如MBR或GPT)的引导加载程序(如GRUB或LILO),引导加载程序将操作系统内核加载到内存中,并将控制权交给内核。内核进行初始化,包括内存管理、设备驱动加载、文件系统挂载等,最后启动用户态进程,负责启动其他用户态服务和应用程序。

配置、编译及调试相关工具

参考资料

Kernel Definition.linfo.2024-05-07

Inside the Mac OS X Kernel.fahrplan.2024-05-09

The Mach Project Home Page.cmu.2024-05-10

操作系统结构.ipads.2024-05-09

System Calls in Operating System Explained.phoenixnap.2024-05-10

操作系统内核之争.腾讯云.2024-05-11

monolithic-architecture.geeksforgeeks.2024-05-08

Operating System Architecture.technologyuk.2024-05-08

Barrelfish Architecture Overview.barrelfis.2024-05-08

Hybrid kernel.microsoft.2024-05-08

Architecture of Windows NT.microsoft.2024-05-08

..2024-05-09

what-is-linux.phoenixnap.2024-07-14

Windows_NT.microsoft.2024-07-14

..2024-05-09

/how-linux-kernel-boots.geeksforgeeks.2024-07-15

KConfig.legato.2024-05-12

GDB(StepbyStepIntroduction).geeksforgeeks.2024-05-12

DDD.gnu.2024-05-12

免责声明
隐私政策
用户协议
目录 22
0{{catalogNumber[index]}}. {{item.title}}
{{item.title}}
友情链接: