操作系统——内存管理
Basic memory management
Base and Limit register
将上图这块称为MMU
Swapping
操作系统中的内存是动态分配的,如图所示:
- A进程启动,占用一部分内存
- B进程启动,占用一部分内存
- C进程启动,占用一部分内存
- A进程结束,又会将之前A占用的内存释放
- 随后又启动D进程,占用掉一部分内存
- B进程结束,释放掉B占用的内存
- 再启动A,这时又会划分给A一部分内存
这些动态的对内存的规划,就要用到swap交换内存,所以一般在linux系统中对交换分区的分区大小是和内存大小一致,或者内存的两倍,就是为了保证交换分区足够大,且高效。
如b图,在程序A中,代码段存在A-Program中,是相对固定的大小。数据段A-Data挨着代码段,当new数据的时候数据段就会增长。在这个进程的地址空间的高端地址会放一个A-Stack,当每次调用一个函数,就会压入A-Stack中(压入栈的叫栈帧),当从函数退出的时候就会弹栈。当数据段和栈碰在一起的时候就溢出了。
Virtual memory
Memory Management with Bit Maps
Memory Management with Linked Lists
-
用Bit Map管理内存
如图(b),A、B、C、D、E表示进程,阴影表示未被分配的内存区域。将内存划分为一个一个的小块,如A进程占用了5个小块。在操作系统的内存中维护一张表map,表中每一个bit对应内存中的一个小块。入A进程与表的第一行的对应,如果该小块内存被占用就用1来表示,如果未被占用就用0来表示。这样维护一张Bit Map就可以管理内存。
-
拉一张链表来管理内存
如图©,链表中一个结点有四个数据:第一个为P/H,如果是P则表示是进程在使用这块内存(Process),如果是H,则表示这块内存未被分配(Hole)。第二个为起始位置,表示这个结点所表示的这块内存的起始位置。第三个表示长度,表示这个结点所表示的内存所占用的长度。第四个指示下一个结点。
当进程所使用的内存被收回后,应该维护这个链表使得保持一致,不可能出现两个Hole连在一起,当一个进程被释放内存后,如果左右有Hole,应该将其合在一起,改变起始位置和长度。
Virtual Memory Paging
当运行一个占用内存很大的进程时,由于物理内存不够用就需要用到虚拟内存。把physical内存分成块,一会儿让这个进程的这部分用,一会儿让另外一部分用。这样就会产生一个类似于swap的从内存和硬盘里的转化的过程。
这里的MMU(Memory management unit)是将虚拟地址转化为实际的物理地址,转化的过程比最开始的那个复杂。首先得知道你要访问的内存在不在物理内存里面,如果不在physical memory
里面,就把你要访问的地址在内存中找个地方加载进来,然后才再去访问它。把不存在的地址加载进内存这件事需要硬件来做,也需要操作系统(操作系统的一个功能——请求分页,用来支持虚拟内存的一个功能)来做。
要知道这个进程里的哪些页在内存里面,哪些不在,如果在,在内存的什么地方,就需要用到虚拟内存里面用到的一个技术——分页(Paging)。MMU会和分页结合起来完成这个虚拟内存。
分页,就是把内存分成固定大小的页帧,把进程里面访问的空间也分成一个一个的页,每个页对应一个页帧,每一个页帧在物理内存可以是不连续的,但是有一个办法可以知道页到页帧之间的转换,这个机制就叫页表(页表存放在操作系统里面)。每个进程都有一个PCB,PCB里有一个数据结构就指向这个进程的页表,每个进程要运行都要一个页表,每个进程的页表都是不一样的。
Address Translation Architecture
logical address也就是虚拟地址,是一个二进制数,低位d表示偏移量直接拿过去,拿到高位(就是p,页帧的编号),在page table中把p作为下表找到对