0.前言
1.了解Linux内存的管理机制(分段分页)
2.了解虚拟内存和物理内存的映射方式
3.了解操作系统内存与磁盘的交互(分页机制---》缺页重读机制,用时拷贝机制)
4.应用程序如何高效使用内存和高级程序的设计方法
1.linux物理使用情况
内核区,用户区,高速缓冲区。内核区与用户区是分割开的,互不影响,不能让用户程序影响内核的程序。linux0.11版本内存大小只有16M.
内存以页为单位管理内存,4K大小
2.逻辑地址 ,线性地址,物理地址
逻辑地址:程序员看到的地址,linux给每一个进程分配一个独立的地址
线性地址:在分段机制下(线性地址=逻辑地址+段基地址) 4G 8G
物理地址:CPU总线的直接地址
在linux0.11版本里面,一个进程给64M的大小,在linux2.6版本,一个进程给4G的大小
分段机制:从逻辑地址---------》》》线性地址上面,根据GDT表(线性地址=逻辑地址+段基地址)
分页机制:线性地址-----------》》》物理内存映射
3.虚拟内存
用户进程使用的都是虚拟内存,linux操作系统的内存管理会进行虚拟内存与物理内存的映射,这个映射就是mmu。
用户使用的是虚拟内存,也就是逻辑地址,当用户需要访问内存数据的时候,需要将这个逻辑地址给到Linux操作系统的管理模块,该模块会进行将逻辑地址映射到物理地址上面的操作。
虚拟内存可以很大,物理内存小,但是不可能所有进程可以同时执行,可以分批执行,合理的调度物理内存的使用
4.分段
大数据分段存储,小数据分页存储。
4.1.GDT
GDT:全局描述符, Intel使用一个48位的寄存器GDTR存储GDT的入口地址;一共256项,4项是内核占用的,剩下252项,一个进程占两项,也就是126个进程,但是linux代码最多支持64个进程,宏定义限制的。
4.2LDT
LDT:局部描述符
LDT描述局部于每个程序的段,包括其代码、数据、堆栈等。LDT是进程的入口地址
5.分页
5.1.分页机制启动
分页机制由CR0中的PG位启用。如PG=1,启用分页机制,并使用本节要描述的机制,把线性地址转换为物理地址。如PG=0,禁用分页机制,直接把段机制产生的线性地址当作物理地址使用。分页机制管理的对象是固定大小的存储块,称之为页(page)。分页机制把整个线性地址空间及整个物理地址空间都看成由页组成,在线性地址空间中的任何一页,可以映射为物理地址空间中的任何一页(我们把物理空间中的一页叫做一个页面或页框(page frame))
5.2.页表
页表存储在CR3寄存器里面
这些页表其实就是索引(这里是二级),加快寻找数据速度
5.3.内存管理两个机制
分页机制:
缺页中断,重加载,利用p位
P位:存在位,P=1表示该项可用,当P=0时,表示该项无效-----缺页中断来源
(缺页异常:在页目录项里面,如果P=0,就先分配一个页表项给页目录项,然后将P=1,让刚刚申请访问的程序重新访问;如果在页表里面,先加载数据到内存里面,然后让P=1,重新访问,然后这样就得到数据,结束过程)
写时复制,读时共享:
fork只是虚拟内存拷贝,但是物理内存是共享的,在vfork里面,虚拟内存都是一样的。
写时:就会引发页面异常,page_fault (中断号为14),该服务函数,会取消共享内存,然后复制一个新的物理页面,然后设置为可读写状态,进行写存在
写存在----》》》页面异常----》》》处理保护异常-------》》》重新分配内存页------》》》重新执行写存在
5.4页寻址
数据是32位,10位用于一级页表,10位用于二级页表,剩下12位给其他权限使用。
P位:存在位,P=1表示该项可用,当P=0时,表示该项无效-----缺页中断来源
(缺页异常:在页目录项里面,如果P=0,就先分配一个页表项给页目录项,然后将P=1,让刚刚申请访问的程序重新访问;如果在页表里面,先加载数据到内存里面,然后让P=1,重新访问,然后这样就得到数据,结束过程)
6.MMU
MMU是一种硬件电路,它包含两个部件,一个是分段部件,一个是分页部件,在此,我们把它们分别叫做分段机制和分页机制,以利于从逻辑的角度来理解硬件的实现机制。分段机制把一个逻辑地址转换为线性地址;接着,分页机制把一个线性地址转换为物理地址。
7.例子
某任务加载后,在4GB虚拟地址空间创建了一个段,起始地址为0x00800000, 段界限为0x5000,字节粒度。当前任务执行时,段寄存器DS指向该段。又假设执行了下面一条指令: mov edx, [0x1050],问此时对应的物理地址是多少?
答:此时,段部件会输出线性地址0x00801050。在没有开启分页机制时, 这就是要访问的物理地址。但现在开启了分页机制,所以这是一个下虚拟地址,要经过页部件转换,才能得到物理地址。
如下图4所示,处理器的页部件专门负责线性地址到物理地址的转换工作。它首先将段部件送来的32位线性地址分为3段,分别是高10位,中间10位,低12位。高10位是页目录的索引,中间10位是页表的索引,低12位则作为页内偏移量来用。
图4
当前任务页目录的物理地址在处理器的CR3寄存器中,假设它的内容为0x00005000 。段管理部件输出的线性地址是0x00801050 。其二进制的形式如图中给出。高10位是十六进制的0x002。它是页目录表内的索引,处理器将它乘以4(因为每个目录项4字节)。作为偏移量访问页目录。最终处理器从物理地址00005008处取得页表的物理地址0x08001000。
线性地址的中间10位为0x001,处理器用它作为页表索引取得页的物理地址。将该值乘以4,作为偏移量访问页表。最终,处理器又从物理地址08001004处取得页的物理地址,这就是我们一直努力寻找的那个页。
页的物理地址是0x0000C000,而线性地址的低12位是数据所在的页内偏移量,故处理器将它们相加,得到物理地址0x0000C050,这就是线性地址0x00801050所对应的物理地址,要访问的数据就在这里。
当任务加载时,操作系统先创建虚拟的段,并根据段地址的高20位决定它要用到哪些页目录项和页表项。然后,寻找空闲的页,将原本应该写入段中的数据写到一个或者多个页中,并将页的物理地址填写到相对应的页表项中。只有这样做了,当程序运行的时候,才能以相反的顺序进行地址变换,并找到正确的数据。