第4章内存管理.ppt
《第4章内存管理.ppt》由会员分享,可在线阅读,更多相关《第4章内存管理.ppt(51页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第4章内存管理 Still waters run deep.流静水深流静水深,人静心深人静心深 Where there is life,there is hope。有生命必有希望。有生命必有希望第4章 内存管理 n本章介绍Linux内存管理子系统的整体概念,讨论存储层次结构、x86存储管理硬件和Linux虚存系统及相关系统工具。4.1存储层次结构和x86存储管理硬件 n n4.1.1内存管理基本框架n nLinux内核的设计要考虑到在各种不同的微处理器上的实现,所以不能仅仅针对i386结构来设计它的映射机制,而要以虚拟的微处理器和内存管理单元MMU(MemoryManagementUnit)为
2、基础,设计出一种通用的模式,再将其分别落实到具体的微处理器上。Linux在内存管理的软件实现方面,提供了不同的接口,可以用于各种各样不同地址线宽度的CPU。n nIntel Intel Intel Intel 的的的的80386803868038680386提供了两层影射的页式内存管理的件提供了两层影射的页式内存管理的件提供了两层影射的页式内存管理的件提供了两层影射的页式内存管理的件支持,一层是页面目录称为支持,一层是页面目录称为支持,一层是页面目录称为支持,一层是页面目录称为PGDPGDPGDPGD(Page DirectoryPage DirectoryPage DirectoryPage
3、 Directory),),),),另一层是页表称为另一层是页表称为另一层是页表称为另一层是页表称为PTPTPTPT(Page TablesPage TablesPage TablesPage Tables),),),),PTPTPTPT的表项称的表项称的表项称的表项称为为为为PTEPTEPTEPTE(Page Table ElementsPage Table ElementsPage Table ElementsPage Table Elements)。)。)。)。通过它们实现从通过它们实现从通过它们实现从通过它们实现从线性地址到物理地址的转换。这种两层影射方式对线性地址到物理地址的转换。这
4、种两层影射方式对线性地址到物理地址的转换。这种两层影射方式对线性地址到物理地址的转换。这种两层影射方式对于于于于32323232位地址线的位地址线的位地址线的位地址线的386386386386是很合适的。但是很合适的。但是很合适的。但是很合适的。但LinuxLinuxLinuxLinux要设计成要设计成要设计成要设计成可在不同的可在不同的可在不同的可在不同的CPUCPUCPUCPU下运行,考虑到大于下运行,考虑到大于下运行,考虑到大于下运行,考虑到大于32323232位地址线宽度位地址线宽度位地址线宽度位地址线宽度的的的的CPUCPUCPUCPU(例如例如例如例如64646464位的位的位的位
5、的CPUCPUCPUCPU),),),),LinuxLinuxLinuxLinux内核的映射机制被内核的映射机制被内核的映射机制被内核的映射机制被设计成设计成设计成设计成3 3 3 3层,在页面目录和页表之间增设了一层层,在页面目录和页表之间增设了一层层,在页面目录和页表之间增设了一层层,在页面目录和页表之间增设了一层“中中中中间目录间目录间目录间目录”PMDPMDPMDPMD(Page Mid-level DirectoryPage Mid-level DirectoryPage Mid-level DirectoryPage Mid-level Directory)在逻辑在逻辑在逻辑在逻辑
6、上,相应地也把线性地址从高到低分为上,相应地也把线性地址从高到低分为上,相应地也把线性地址从高到低分为上,相应地也把线性地址从高到低分为4 4 4 4个位段,各个位段,各个位段,各个位段,各占若干位,分别用作目录占若干位,分别用作目录占若干位,分别用作目录占若干位,分别用作目录PGDPGDPGDPGD的下标、中间目录的下标、中间目录的下标、中间目录的下标、中间目录PMDPMDPMDPMD的下标、页表中的下标和物理页面内的位移。如图的下标、页表中的下标和物理页面内的位移。如图的下标、页表中的下标和物理页面内的位移。如图的下标、页表中的下标和物理页面内的位移。如图4.14.14.14.1所示。所示
7、。所示。所示。PGDPGDPGDPGD、PMDPMDPMDPMD、PTPTPTPT都是数组。都是数组。都是数组。都是数组。Page FramePage FramePage FramePage Frame是最是最是最是最后得到的物理页。后得到的物理页。后得到的物理页。后得到的物理页。三层影射过程如下:(1)从控制寄存器CR3中找到页目录的基址。(2)以线性地址的最高位段作为下标在PGD中找到确定中间目录的表项的指针。(3)以线性地址的次位段作为下标在PMD中找到确定页面表的表项的指针。(4)在线性地址的接下来位段为下标在PTE中找到页的指针。(5)最后线性地址的位段中为在此页中偏移量。这样,最终
8、完成了线性地址到物理地址的转换。n n假如当要执行某个函数的第一个句子时,假如当要执行某个函数的第一个句子时,CPUCPU会通过会通过3232位地址线寻址(位地址线寻址(2 2的的3232次方,可以寻址次方,可以寻址4 4GG的线性地址空间)。通过的线性地址空间)。通过MMUMMU执行以上的影射过程,执行以上的影射过程,就会在计算机的内存中找到这个句子的物理地址,如果要找的那一句不在物就会在计算机的内存中找到这个句子的物理地址,如果要找的那一句不在物理页中,就会发生一次异常中断,使硬盘和内存发生交互。理页中,就会发生一次异常中断,使硬盘和内存发生交互。n n在在LinuxLinux原码的原码的
9、 include/asm-i386/gptable.hinclude/asm-i386/gptable.h定义了能够包容不同定义了能够包容不同CPUCPU的的接口:接口:n n#ifCONFIG_X86_PAE/ifCONFIG_X86_PAE/假如在假如在PAEPAE模式下,用三层影射结构模式下,用三层影射结构n n#includeincluden n#else#elsen n#include/#include/否则用两层否则用两层n n#endifendifn n在在pgtable-2level.hpgtable-2level.h中定义了中定义了PGDPGD,PMDPMD的结构。的结构。n
10、 n#definePGDIR_SHIFT22/definePGDIR_SHIFT22/页目录是线性地址的页目录是线性地址的31223122位位n n#definePTRS_PER_PGD1024/definePTRS_PER_PGD1024/总共有总共有10241024个页目录个页目录n n#definePMDIR_SHIFT22/definePMDIR_SHIFT22/中间目录不用了中间目录不用了n n#definePTRS_PER_PMD1definePTRS_PER_PMD1n n#definePTRS_PER_PTE1024/#definePTRS_PER_PTE1024/每个页表有每
11、个页表有10231023页页n n在在3232位线性地址中的位线性地址中的4 4GG虚拟空间中虚拟空间中,其中有其中有1 1GG做为内核空间做为内核空间,从从0 0XC0000000XC0000000到到0 0XFFFFFFFFXFFFFFFFF。每个进程都有自己的每个进程都有自己的3 3GG用户空间,用户空间,它们共享它们共享1 1GG的内核空间。当一个进程从用户空间进入内核空间时,的内核空间。当一个进程从用户空间进入内核空间时,它就不在有自己的进程空间了。它就不在有自己的进程空间了。n n在物理空间中,内核总是从在物理空间中,内核总是从0 0地址开始的,而在虚拟空间中是丛地址开始的,而在虚
12、拟空间中是丛0 0XC0000000XC0000000开始的。内核中的影射是很简单的线性影射,所以开始的。内核中的影射是很简单的线性影射,所以0 0XC0000000XC0000000就是两者的偏移量。就是两者的偏移量。n n在在page.hpage.h中:中:n n#define_PAGE_OFFSET(0 xc0000000)define_PAGE_OFFSET(0 xc0000000)n n#definePAGE_OFFSET(unsignedlong)_PAGE_OFFSET)#definePAGE_OFFSET(unsignedlong)_PAGE_OFFSET)n n#defne_
13、pa(x)(unsignedlonsg)(x)PAGE_OFFSET)#defne_pa(x)(unsignedlonsg)(x)PAGE_OFFSET)n n/内核虚拟地址转换到物理地址内核虚拟地址转换到物理地址n n#define_va(x)(void*)(unsignedlong)(x)+define_va(x)(void*)(unsignedlong)(x)+PAGE_OFFSET)PAGE_OFFSET)n n/内核从物理地址到虚拟地址的转换内核从物理地址到虚拟地址的转换n n 对对i386i386微处理器来说,微处理器来说,CPUCPU实际上不是按实际上不是按3 3层而是按两层的模
14、型来进层而是按两层的模型来进行地址映射,这就需要将虚拟的行地址映射,这就需要将虚拟的3 3层映射落实到具体的两层的映射,层映射落实到具体的两层的映射,跳过中间的跳过中间的PMDPMD层次。层次。n n4.1.2地址映射的全过程地址映射的全过程n n80386有实方式和保护方式两种工作方式。尽管实方式下80386的功能较Intel先前的微处理器有很大的提高,但只有在保护方式下,80386才能真正发挥作用。在保护方式下,全部32根地址线有效,可寻址达4G字节的物理空间。扩充的存储器分段管理机制和可选的存储器分页管理机制,不仅为存储器共享和保护提供了硬件支持,而且为实现虚拟存储器提供了硬件支持;支持
15、多任务,能快速的进行任务切换和任务保护环境;4个特权级和完善的特权检查机制,既能实现资源共享又能保证代码及数据的安全和保密及任务的隔离;支持虚拟8086方式,便于执行8086代码。(1)80386 保护方式的寻址在保护方式下,当寻址扩展内存中的数据和程序时,仍然使用偏移地址访问位于存储器内的信息,但保护方式下的段地址不再像实方式那样有段寄存器提供,而是在原来存放段地址的段寄存器里含有一个选择子,用于选择描述符表内的一个描述符。描述符描述存储器的位置、长度和访问权限。保护方式下有两个描述符表:全局描述符表和局部描述符表。全局描述符表包含适用于所有程序的段定义,而局部描述符表通常用于唯一的应用程序
16、。每个描述符表包含8129个描述符,所以任何时刻应用程序最多可用16384个描述符。每个描述符长8字节,全局和局部描述符表每个最长为64kb。分页机制式存储管理机制的第二部分。分页机制在段机制之后进行操作,以完成虚拟地址到物理地址的转换。段机制把虚拟地址转换为线性地址,分页机制进一步把线性地址转换为物理地址。分页机制由微处理器中控制寄存器的内容控制。分页机制由CRO中的PG位启用。若PG=1,启用分页机制。PG=0,不用分页机制,直接把段机制生成的线性地址当作物理地址。软件生成的线性地址分为三部分,分别用于页目录项、页表项和页偏移地址寻址。(2)Linux所采用的方法i386微处理器一律对程序
17、中的地址先进行段式映射,然后才能进行页式映射。而Linux为了减小footprint,提高cache命中率,尽量避免使用段功能以提高可移植性。如通过使用基址为0的段,使逻辑地址等于线性地址。因此Linux所采用的方法实际上使i386的段式映射的过程不起作用。下面通过一个简单的程序来看看Linux下的地址映射的全过程:#includegreeting()printf(“Helloworld!”);main()greeing();该程序在主函数中调用greeting来显示“Helloworld!”,经过编译和反汇编的结果如下。08048568:8048568:55push1%ebp8048856b
18、:89e5mov1%esp,%ebp804856b:6804940408push1$0 x80484048048570:e8fffeffffcall80484748048575:83c404add1$0 x4,%esp8048578:c9leave8048579:c3ret804857a:89f6mov1%esi,%esi0804857c:804857c:55push1%ebp804857d:89e5mov1%esp,%ebp804857f:e8e4ffffffcall80485688048584:c9leave8048585:c3ret8048586:90nop8048587:90nop从上
19、面可以看出,greeting()的地址为0 x8048568。在elf格式的可执行代码中,总是在0 x8000000开始安排程序的“代码段”,对每个程序都是这样。程序在main中执行到了“call8048568”这条指令,要转移到虚拟地址8048568去。首先是段式映射阶段。地址8048568是一个程序的入口,更重要的是在执行的过程中由CPU的EIP所指向的,所以在代码段中。I386cpu使用CS的当前值作为段式映射的选择子。内核在建立一个进程时都要将它的段寄存器设置好,把DS、ES、SS都设置成_USER_DS,而把CS设置成_USER_CS,这也就是说,在Linux内核中堆栈段和代码段是不
20、分的。IndexTIDPL#define_KERNEL_CS0 x100000000000010|0|00#define_KERNEL_DS0 x180000000000011|0|00#define_USER_CS0 x230000000000100|0|11#define_USER_DS0 x2B0000000000101|0|11_KERNEL_CS:index=2,TI=0,DPL=0_KERNEL_DS:index=3,TI=0,DPL=0_USERL_CS:index=4,TI=0,DPL=3_USERL_DS:index=5,TI=0,DPL=3TI全都是0,都使用全局描述表。内
21、核的DPL都为最高级别0;用户的DPL都是最低级别3。_USER_CS在GDT表中是第4项,初始化GDT内容的代码如下:ENTRY(gdt-table).quad0 x0000000000000000/NULLdescriptor.quad0 x0000000000000000/notused.quad0 x00cf9a00000ffff/0 x10kernel4GBcodeat0 x00000000.quad0 x00cf9200000ffff/0 x18kernel4GBdataat0 x00000000.quad0 x00cffa00000ffff/0 x23user4GBcodeat0
22、 x00000000.quad0 x00cff200000ffff/0 x2buser4GBdataat0 x00000000GDT表中第1、2项不用,第3至第5项共4项对应于前面的4个段寄存器的数值。将这4个段描述项的内容展开:K_CS:0000000011001111100110100000000000000000000000001111111111111111K_DS:0000000011001111100100100000000000000000000000001111111111111111U_CS:000000001100111111111101000000000000000000
23、00000001111111111111111U_DS:0000000011001111111100100000000000000000000000001111111111111111这4个段描述项的下列内容都是相同的。BO-B15/B16-B31都是0基地址全为0LO-L15、L16-L19都是1段的界限全是0 xfffffG位都是1段长均为4KBD位都是132位指令P位都是1四个段都在内存中不同之处在于权限级别不同,内核的为0级,用户的为3级。由此可知,每个段都是从地址0开始的整个4GB地虚存空间,虚地址到线性地址的映射保持原值不变。再回到greeting的程序中来,通过段式映射把地址80
24、48568映射到自身,得到了线性地址。每个进程都有自身的页目录PGD,每当调度一个进程进入运行时,内核都要为即将运行的进程设置好控制寄存器CR3,而MMU硬件总是从CR3中取得当前进程的页目录指针。当程序要转到地址0 x8048568去的时候,进程正在运行中,CR3已经设置好了,指向本进程的页目录了。8048568:00001000000001001000010101101000按照线性地址的格式,最高10位0000100000,十进制的32,就以下标32去页目录表中找其页目录项。这个页目录项的高20位后面添上12个0就得到该页面表的指针。找到页表后,再看线性地址的中间10位001001000
25、,十进制的72。就以72为下标在找到的页表中找到相应的表项。页面表项重的高20位后添上12个0就得到了物理内存页面的基地址。线性地址的底12位和得到的物理页面的基地址相加就得到要访问的物理地址。4.1.3 地址映射的效率分析地址映射的效率分析在页式映射的过程中,CPU要访问内存3次,第1次是页面目录,第2次是页面表,第3次才是真正要访问的目标。这样,把原来不用分页机制一次访问内存就能得到的目标,变为3次访问内存才能得到,执行分页机制在效率上的牺牲太大。为了减少这种开销,最近被执行过的地址转换结果会被保留在MMU的转换后备缓存(TranslationLook-asideBuffer,TLB)中。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 内存 管理
限制150内