内存管理
计算机在处理每一个程序时,就要为程序分配内存,每次分配内存时,地址都是从0开始。这时程序的地址叫做逻辑地址。计算机内存的地址叫物理地址,物理地址是从0开始的连续区域。然而,当程序执行时,这个计算机程序在计算机内存中存储位置不一定是从0开始的。
物理内存层面,常常会把内存划分成不同的区域。可以划分成不同大小,也可以划分成相同大小。分区,分段存储方式一般是把内存划分成不同大小的块的,而分页则是划分成相同大小的块。
实现逻辑地址向物理地址的转换。 实现多进程下的内存分配。 对各个用户的内存空间实施保护。 必要时,对逻辑主存进行扩充。
一句话,就是外存当内存用,计算机在运行程序时,只是把程序的一部分代码放入内存运行,一部分放在内存之外的虚拟内存中,当有需要的时候,直接从虚拟外存中调入即可。减小内存压力。
地址映射这个地方我学到了很多c++的知识。主要可以联想c++程序的开发阶段。即编写,编译,连接,运行,这四个方面。
c++程序在编译时,就是给那些代码分配内存空间,(除了new分配的那些内存)。如果这个时候,就把逻辑地址转换为物理地址。运行的时候,就可以直接去物理内存拿数据了。但是,这样的话,那么,程序运行时的物理地址就固定了。?这样做,缺点是啥?
运行的时候,首先装入内存任意位置,接着发生地址转换。然后就把移动程序到转换后物理地址。
程序在运行时,当执行某条语句时,通过一个特定的地址转换机构实现逻辑地址到物理地址的转换。由硬件实现,你可以弄个基址寄存器,逻辑地址加上基址寄存器得到物理地址。
由于物理地址是一维连续的空间,所以把逻辑地址也划分成一维的。
把程序分为若干模块。一个程序有代码段,数据段,栈段,特别分段。我们编译时就把这些分开,每一段都有指向指向这个段的指针和段内偏移量。 好处呢 将不同代码区分开,更加方便管理。 动态链接,运行的时候需要段这个再去链接过来。
• 主存资源信息块
• 分区描述器和空闲队列
• 分区的分配与回收
某一时刻,内存中出现很多碎片,这些碎片互不相邻,所以内存回收时无法合并。同时,这些碎片的总容量足够大,但每一个碎片不能存储一个程序。这时,我们我们需要把这些碎片合并起来。移动已分配的内存空间到别的位置,使得碎片相邻,我们就可以合并碎片了。这种技术叫拼接技术 内存回收时拼接 当不够时再拼接 缺点: 移动已分配的内存,消耗大量cpu时间。成本太高。 当移动时,当前进程阻塞,对于对需要迅速及时响应的进程极不友好。 那么如何减少碎片化问题呢?接下来轮到分页管理登场。
我们把逻辑地址划分成不同的页,每一页放到物理内存的一个等大的块儿中,这样就能极大减少碎片化问题。这个和固定分区很像,但是固定分区并没有划分逻辑地址,如果分页的页数只有一页,那就和固定分区一样了。每一页的大小与物理内存快的大小相等,为2的n次幂。
页面如何映射到内存块,答案是采用页表。一个页表最基本要有两个字段:页号,物理内存快号。 逻辑地址组成:页号x,页内偏移量y 页表的存储: 1.可以放在内存中。这样访问一个数据就要访问两次内存。 2.放在cache中。提高查找速度,同时成本太高了。 3.一部分页表放在内存中,一部分放在cache中。访问数据中,首先查找cache中的页表(快),如果有,则去访问物理内存,直接拿数据。如果没有,则到内存中去查找,接着把条记录放到cache中,cache中满了咋办,一般淘汰最先进入的那条记录。 好像操作系统学过这玩意儿,当时考试还没回答上来。现在一想,cache中可以用队列来存这玩意儿,一旦队列满了,就出队列。
当访问的页面不在内存中,就要从虚拟内存中调入页面。如何判断页面在不在内存中?如果不在,在哪里? 1.第一个问题,我们可以给页表加入一个中断位i,i == 0表示在内存中,i!=0表示不在内存中。 2.第二个问题可以通过加一个外存地址字段。 访问页表大概的流程如下: 访问页表,查看中断位。如果中断位为0,说明页面在内存中,直接去物理内存中拿数据。如果中断位为不为0,发生缺页中断,cpu保护现场,阻塞当前进程,转入调页程序,将外存中的页面放入内存中,更改页面中断位为1,唤醒当前进程,当前进程去内存中拿数据。
从外存中索取页面放入内存中,内存空间已满,则需要淘汰内存某些页面。 抖动现象:要是淘汰算法没设计好,可能出现这样一种情况,内外存频繁交换,系统效率急剧下降,这种现象叫抖动或者颠簸。
原文:https://www.cnblogs.com/jielearscoding/p/12632403.html