操作系统软件治理之内存管理

随着工作越来越深入,深觉从前学的东西都是一个一个孤立的点,不经过思考和整理,无法串连成网络。虽然目前的工作更加偏向上层,但是没有底层逻辑的坚实支撑,上层修炼再多也容易头重脚轻。最近有空在看计算机基础架构方面的东西,见缝插针地做些整理,不求形成体系,但愿集腋成裘,至少能将硬件、软件、架构在意识里能够统一起来。

今天就来聊聊操作系统在管理软件时,是如何分配内存的。

我们都知道,操作系统的核心职能就是软件治理。软件通过CPU运行,而CPU可以直接访问的存储资源包含寄存器、内存(RAM)和主板上的ROM。寄存器是CPU的组成部分,它的访问速度非常快,但数量较少,大部分程序员不会直接跟寄存器打交道,编程语言的编译器会根据需要自动选择寄存器来优化程序的运行性能;而主板上的ROM为非易失的只读存储,用来存储计算机的启动程序BIOS;因此,跟程序员写的应用程序相关的核心存储资源,就是内存了。但内存资源也是有限的,那么当有多个软件共同运行时,操作系统是如何保证有足够的内存分配给每个进程呢?这就涉及到了操作系统的内存管理。

CPU对内存的读取有两种模式:实模式和保护模式。这两种模式下CPU对内存操作的方式有很大的差别。在实模式下,CPU通过物理地址直接访问内存;而在保护模式下,CPU首先通过一个地址映射表把虚拟的内存地址转换为物理内存地址,再去读取数据。相应地,工作在实模式下的操作系统叫做实模式操作系统;工作在保护模式下的操作系统叫做保护模式操作系统。我们现在使用的计算机,绝大多数都是保护模式操作系统,实模式操作系统大多存在于早期的计算机,如8086。

在实模式下,操作系统将软件从外置存储(如硬盘)中读入到内存并执行。在加载时,将软件中的数据和函数地址固定到内存的物理地址,然后才能执行。在这种模式下,所有软件,包括操作系统本身,都处在同一个物理地址空间下,那么操作系统是如何为每个软件分配内存的呢?有两种方式:

(1) 把操作系统内存管理函数放在一个公共的地方,每个软件想申请内存,便到这个地方取得内存管理函数并调用;

(2) 采用中断方式实现内存管理功能。内存管理中断是一种软中断,位于操作系统中断向量表的第77项。

以上我们可以看出,由于软件都在同一个内存地址空间运行,因此就存在一些问题:(1) 不同的软件相互之间可以访问对方的数据甚至指令,容易造成安全风险,比如老版的windows经常出现的黑屏或死机,可能就是用户程序异常修改了系统内核的指令或数据;(2) 能够支持的软件复杂度低,且可以并行运行的程序数量少。这是因为毕竟内存大小是有限的,当程序所需内存空间大小超过内存实际大小时,程序就无法运行。

那么这个时候,保护模式就该出场了。

在保护模式下,CPU对内存的访问,不再是直接访问内存的物理地址,而是通过虚拟内存的方式。那什么是虚拟内存呢?我个人的理解,虚拟内存是操作系统内存管理的一种技术,是一个概念,而不是一个特定的实体。它的作用就是让每个程序都“认为”自己拥有连续且完整的地址空间,而不用去关心物理内存是否足够。实际上,每个程序的空间在存储实体上是被分成多个片段(一般是页,或者段,或者段页结合),程序在运行时,活动片段被加载到物理内存中,而非活动片段保留在磁盘上,且随着程序的运行,根据需要进行不同片段的交换。

                                                                            本图来自于许世伟的架构课

CPU在访问某个虚拟内存地址中的数据时,先计算出要访问哪个内存页,然后通过地址映射表,将虚拟内存的逻辑地址转换为物理内存地址,然后再到对应的物理内存地址去读取数据。如果某个虚拟内存页没有存在于物理内存上,也就是找不到对应的物理内存地址,这种情况叫做“缺页”,这时CPU就会发起一个缺页中断请求。操作系统响应该中断请求,并为该内存页分配物理内存,如果没有足够的物理内存为之分配,则会选择一个最久没有被访问的内存页将其淘汰,当然,淘汰该内存页之前会将其数据保存起来,以便下次要访问它的时候再将它交换进来。

由于是虚拟的地址空间,操作系统理论上可以为软件分配任意大的虚拟内存(当然,也要考虑计算机实际磁盘的大小)。每个运行中的软件,都有自己的地址映射表,也就是虚拟地址并不是全局的,每个进程都有自己的独立虚拟地址空间。通过虚拟内存和缺页机制,CPU就很好地解决了操作系统和软件的配合关系。

发布了57 篇原创文章 · 获赞 58 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/DeliaPu/article/details/90047301