在生活中,很多人都不知道内存管理_操作系统是如何管理内存的是什么意思,其实他的意思是非常简单的,下面就是小编搜索到的内存管理_操作系统是如何管理内存的相关的一些知识,我们一起来学习下吧!

内存管理(操作系统如何管理内存)

在计算机世界里,有两种宝贵的资源,CPU和内存。这是每个进程都必须争夺的资源。本文讨论操作系统如何管理内存。由于水平有限,涉及内存管理的细节较多,这里只是介绍一些内存管理的关键概念和开发流程。


(资料图片)

面对物理记忆

很久很久以前,内核和用户进程都直接操作物理内存。这时,物理内存模型可以简化如下。物理内存按照固定的大小编号,每个数字代表一个固定的二进制位。我们使用物理内存号码,就像门牌号一样。这种模式的特点是简单、直接,但也带来了许多严重的问题。

1:用户进程间内存冲突。

在这种模式下,如果多个进程同时运行,就会造成内存冲突。例如,进程A访问第16个物理内存,而进程B也可能访问第16个物理内存,从而导致冲突。相当于你想进16号房间,另一个人想进同一个房间。最后,你们两个一定会合作。

2:破坏操作系统。

因为内核和用户进程都是直接操作物理内存的,所以不可避免的会运行用户程序来操作内核使用的内存,造成系统瘫痪。

其实这种模式也不是一无是处。因为足够简单,直接操作硬件,所以在简单嵌入式系统、收音机、微波炉的计算机版本中,仍然采用这种方法。对了,BIOS也用这个方法。

去吧,既然这个方案有很多严重的问题,那么我们需要找一个新的方案。注意,我们要解决的问题是同时运行多个进程,但不会造成物理内存地址冲突。

地址空

Address 空:进程可以用来寻址内存的一组地址空空间。每个进程都有自己的地址空,并且这个地址空独立于其他进程的地址空(除了一些特殊情况,可以共享)。

address 空的概念类似于我们的 *** 号码。比如我们的手机号就是一个由11个 *** 数字组成的地址空。address 空这个概念在生活中还有很多其他的应用。

基址寄存器和极限寄存器

虽然每个进程都有自己的地址空(如下图A和B所示),但是访问物理地址冲突的问题并没有得到解决。因为进程A的第16个内存和进程B的第16个内存很可能是同一个内存。

为了解决这个问题,发明了两种特殊的硬件,基址寄存器和极限寄存器。(关键时刻需要硬件工程师)

基址寄存器:存储进程访问的内存的起始地址。

极限寄存器:存储进程的内存长度。

例如

之一个程序运行时,基址寄存器和极限寄存器的值分别为0,16384,第二个程序运行时,这些值分别为16384和32768。如果第三个16KB的程序进来,基址寄存器的值是32768和16384。如下图所示

每个进程的内存地址被发送到物理内存之前。将自动添加基址寄存器的值。这样每个进程都会在固定的内存范围内活动,可以解决多个进程同时在内存的问题。为了避免用户进程任意改变寄存器中的值而导致的内存访问错误,在许多系统中,基址寄存器和极限寄存器只能由操作系统访问。

这种模式看似完美解决了多程序运行的问题,但问题是每次访问内存都要做加法和比较,加法速度太慢。而且进程的内存是动态变化的,所以这种方法不是更优解。

交换内存

我们先来看另一个问题——内存过载。每个程序员都希望拥有无限的内存,但这并不现实。就像你想拥有无限的金钱一样。软件膨胀的速度和人的欲望一样,永远不会满足。

交换内存(Swap memory):一个进程在运行一段时间后,被完全装入内存并存储在磁盘中。然后将另一个进程加载到内存中,继续运行。周期 *** 替空空闲进程主要存储在磁盘上。

这种方案不仅可以解决同时运行多个进程的问题,还可以解决内存过载的问题。由于数据频繁写入磁盘,硬盘的写入速度远不及内存。所以这个方案不是我们要找的更优方案。值得一提的是,虽然这种方案不能作为主流的内存管理方案,但是交换内存的概念却被保留了下来,并在实际应用中发挥了很大的作用,这一点后面会讲到。

虚拟内存

以解决同时运行多个程序和内存过载的问题。所有操作系统的终极解决方案-虚拟内存。虚拟内存概念的强大之处在于,只有当程序的一部分被加载到内存中时,程序才能运行。您不必像上面描述的那些模型那样,加载所有的内存来运行该进程。

虚拟内存:每个程序都有自己的虚拟地址空,这个空又被分成几个块,每个块称为一个页面。每页都有连续的地址空。这些也映射到物理内存。但不是所有的页面都必须在内存中才能运行程序。当程序引用的页面在物理内存中时,映射由操作系统完成。当程序访问的页面不在物理内存中时(缺页中断),操作系统负责将所需页面加载到内存中。当一个程序等待一些内容读入内存时,它可以把CPU让给其他进程。

上一段有几个重点。让我给你整理一下。

虚拟地址

程序能寻址的更大空房间,所谓的虚拟地址,逻辑上是虚的,实际没那么大。32位操作系统的更大虚拟地址空为2 ^ 32空约为4G,64位操作系统的更大虚拟地址空为2 ^ 64。抱歉,我想不出有多大。

虚拟地址空按照固定的大小分成若干个单元,称为页面。

页面

物理内存中对应虚拟页面的单位称为页帧。页面和框架通常大小相同。

如何映射内存管理单元和页表?

将虚拟地址发送到内存管理单元,MMU包含在CPU中),然后通过页表将虚拟地址映射到物理地址。页面的本质是一个函数,输入一个虚拟地址,输出一个真实的物理地址。

缺页中断

我们知道进程的虚拟地址空很大,但是物理内存肯定没有那么大,也就是不可能把所有的虚拟地址都映射到物理内存。当被访问的页面不在物理内存中时,就会发生页面中断。此时,需要页面调度算法将暂时不需要的页面替换到交换区,并将需要的页面加载到内存中。在等待页面切换时,CPU将处理其他进程。Linux会在磁盘中设置一个专门的区域作为内存的交换区域,这个区域不同于IO系统的disk 空。

例如

让我们简单看一下如何将虚拟内存地址映射到真实的物理内存地址。假设有一台计算机可以生成16位地址。更大寻址范围是0到64K(2 ^ 16)。这台计算机的实际物理内存是32K。虽然我们可以编写64K的程序,但是不能完全加载到内存中。磁盘上必须有64K 空的空间,保证需要的时候可以把程序片段加载到内存中。如下图

共用存储器

为了更有效地使用内存,我们希望共享更多的内存。

多进程共享页面

实际上,指令空和数据空通常是分开的。指令空之间的页面很容易共享,因为指令空之间的内容是只读的。如果该页在data 空之间共享,请确保该数据是只读的,或者在data 空之间写入时 *** 一个副本。比如fork调用,只要一个进程写,就会复制一个副本,让每个进程都能读写。这个过程称为写入时复制。

多进程共享库

这是共享内存的另一个方面。共享页面是根据页面维度共享的,这是基于库维度的。很多进程会使用相同的底层库,比如windows的动态链接库(DLL)。这样内存中只加载一个副本就可以了,大大节省了内存空。

结束

以上内容大概介绍了操作系统内存管理的基础知识,但是还有很多细节没有涉及到,比如页面置换算法,如何更快的将虚拟地址映射到物理地址。如何处理过程中动态内存增长等问题?有兴趣可以私信我或者查阅相关书籍。

关键词: 内存管理