第四章存储器管理在Linux系统中,存储器管理。需要掌握以下基本内容–存储器管理的基本概念–虚拟存储器地址与空间类型–内存分页机制与MMU–虚拟内存的申请与释放学习目标主要内容132进程虚存空间的管理分页机制与MMU虚拟内存的申请与释放一、进程虚拟存储空间的管理1.存储器管理基本概念2.进程的虚存区域3.虚存空间的映射和虚存区域的建立在Linux系统中,存储器管理。需要掌握以下基本内容–存储器管理的基本概念–虚拟存储器地址与空间类型–内存分页机制与MMU–虚拟内存的申请与释放学习目标主要内容132进程虚存空间的管理分页机制与MMU虚拟内存的申请与释放一、进程虚拟存储空间的管理Linux系统:采用的是段页式内存管理–80x86(32位)中,逻辑页面大小为4KB,每个页表项占4B采用请求调页技术实现虚拟存储用“最近最少使用”(LRU)算法进行页面置换采用伙伴算法实现内存的分配与回收每一个要运行的程序,必须首先进入内存,然而,每一台计算机的内存容量都是有限而宝贵的。存储管理的任务是方便用户使用存储资源,在有限的物理空间内使更多的用户进程高效地获得和使用尽可能多的存储空间,从而提高系统的整体性能。现代操作系统中普遍采用基于虚拟存储器的概念来统一管理内存和外存,实现逻辑上的大容量存储空间。1、存储管理基本概念一、进程虚拟存储空间的管理虚拟存储器–计算机系统的存储器分为内存(主存)和外存(硬盘)。使更多的用户进程合理、充分地使用存储资源,操作系统统一管理内存和外存,即把内存中暂时不用的内容放在硬盘上,内存中就可以腾出一部分空间,可以从硬盘装入其他迫切需要的内容。因此,从效果上看,计算机系统好像为用户提供了一个其存储容量比实际主存大得多的存储器。人们称这个存储器为虚拟存储器。–虚拟存储器:在具体层次存储器的计算机系统中,采用自动失效部分装入和部分对换的功能,为用户提供一个比物理主存容量大得多的,可寻址的移植“主存储器”,虚拟存储器是为扩大主存而采用的一种设计技巧。–虚拟存储器的容量和主存没有直接关系。1、存储管理基本概念一、进程虚拟存储空间的管理1、存储管理基本概念地址空间–地址空间(addressspace)是一段表示内存位置的地址范围(ARM体系结构)。•物理地址空间:真实的硬件内存地址•逻辑地址空间,也称为虚拟地址空间,CPU所能处理的地址空间的总和–对于32位CPU而言,它的逻辑地址空间是4G。–采用逻辑地址空间的好处是每个用户进程都有自己独立的运行空间,而不用管自己在物理内存的实际位置。–在Linux系统中,4G的地址空间由Linux内核与Linux应用程序共同分享。一、进程虚拟存储空间的管理1、存储管理基本概念一、进程虚拟存储空间的管理Linux的虚拟地址划分–每一个用户进程都可以访问4GB的虚拟内存空间–从0-3GB的虚拟内存地址是用户空间,用户进程可以直接对其进行访问。–从3GB-4GB的虚拟内存地址为核心态空间,存放仅供核心态访问的代码和数据,用户态进程不能访问。用户进程只有通过中断或系统调用才可以进入核心态。–所有进程从3GB到4GB的虚拟空间都是一样的,有同样的页目录项,同样的页表,对应到同样的物理内存段。Linux以此方式让内核态进程共享代码段和数据段——共享虚拟内存机制。Linux虚拟地址划分(在Linux内核的低版本中(2.0.X))–各进程拥有自己的3G用户空间(从0x00000000到0xBFFFFFFF共3GB)–内核占用最高的1G作为系统空间(从0xC0000000到0xFFFFFFFF的1GB),系统空间由所有进程共享1、存储管理基本概念一、进程虚拟存储空间的管理Linux的虚拟内存映射–在逻辑地址和物理地址之间相互转化的工作是由内核和硬件内存管理单元(MMU)共同完成的。MMU是CPU芯片内部的一部分。–内核告诉MMU如何为每个进程把某逻辑页面映射到某特定物理页面,而MMU在进程提出内存请求时完成实际的转化工作——动态地址映射方式。1、存储管理基本概念一、进程虚拟存储空间的管理内核空间和用户空间–进程运行时能访问的存储空间只是它的虚拟内存空间。对当前该进程而言只有属于它的虚拟内存是可见的。–在进程的虚拟内存包含着进程本身的程序代码和数据。–进程在运行中还必须得到操作系统的支持。进程的虚拟内存中还包含着操作系统内核。–Linux把进程的虚拟内存分成两部分,内核区和用户区。–进程虚拟内存的内核区的访问权限设置为0级,用户区为3级。一、进程虚拟存储空间的管理2、进程虚拟空间的管理内核空间和用户空间–Linux操作系统采用了请求式分页虚拟存储管理方法。系统为每个进程提供了4GB的虚拟内存空间。各个进程的虚拟内存彼此独立。–Linux的存储管理主要是管理进程虚拟内存的用户区。进程虚拟内存的用户区分成代码段、数据段、堆栈以及进程运行的环境变量、参数传递区域等。一、进程虚拟存储空间的管理2、进程虚拟空间的管理一、进程虚拟存储空间的管理2、进程虚拟空间的管理linux只定义了四种段寄存器的取值内核代码段0x10内核数据段0x18用户代码段0x23用户数据段0x28include/asm-i386/segment.h中定义的:#define__KERNEL_CS0x10#define__KERNEL_DS0x18#define__USER_CS0x23#define__USER_DS0x2B表明:使用的都是全局描述符表(GDT,包含着系统中所有任务都可用的那些描述符)进程对段访问的请求权限(RPL),运行级别只用了0和3两级,内核为0级,用户进程为3级。一、进程虚拟存储空间的管理2、进程虚拟空间的管理2、进程虚拟空间的管理一、进程虚拟存储空间的管理Linux运行在x86时,进程的虚拟内存为4GB。进程虚存空间的划分在系统初始化时由GDT确定,它定义在/arch/i386/kernel/head.S文件中:ENTRY(gdt_table).quad0x0000000000000000/*NULL描述符*/.quad0x0000000000000000/*未使用*/.quad0xc0c39a000000ffff/*内核代码段1GB在0xc0000000*/.quad0xc0c392000000ffff/*内核数据段1GB在0xc0000000*/.quad0x00cbfa000000ffff/*用户代码段3GB在0x00000000*/.quad0x00cbf2000000ffff/*用户数据段3GB在0x00000000*/.quad0x0000000000000000/*未使用*/.quad0x0000000000000000/*未使用*/.fill2*NR_TASKS,8,0/*各个进程LDT描述符和TSS描述符的空间*/一、进程虚拟存储空间的管理Linux运行在ARM时,进程的虚拟内存为4GB。它定义在/arch/arm/kernel/head-armv.S文件中:从表面上看内核的基地址变为了0,但实际上,内核通常仍在虚址3G以上。其中奥妙在于不同的连接描述文件:通过使用页机制提供的保护,阻止了用户程序访问内核空间。2、进程虚拟空间的管理ENTRY(gdt_table).quad0x0000000000000000/*NULLdescriptor*/.quad0x0000000000000000/*notused*/.quad0x00cf9a000000ffff/*0x10kernel4GBcodeat0x00000000*/.quad0x00cf92000000ffff/*0x18kernel4GBdataat0x00000000*/.quad0x00cffa000000ffff/*0x23user4GBcodeat0x00000000*/.quad0x00cff2000000ffff/*0x2buser4GBdataat0x00000000*/.quad0x0000000000000000/*notused*/.quad0x0000000000000000/*notused*/一、进程虚拟存储空间的管理2、进程虚拟空间的管理实例分析映射机制通过前面的理论分析,通过编写一个简单的程序,来分析内核是如何把线性地址映射到物理地址的。[root@localhosttemp]#cattest.c#includestdio.hvoidtest(void){printf(hello,world.\n);}intmain(void){test();}这段代码很简单,故意要main调用test函数,就是想看下test函数的虚拟地址是如何映射成物理地址的。一、进程虚拟存储空间的管理2、进程虚拟空间的管理实例分析映射机制在反汇编下test文件[root@localhosttemp]#gcc-otesttest.c[root@localhosttemp]#objdump-dtestld给test()函数分配的地址为0x08048328.并且CPU正在执行main()中的call8048328这条指令,要转移到虚拟地址0x08048328去运行.实例分析映射机制首先是段式映射阶段。由于0x08048328是一个程序的入口,更重要的是在执行的过程中是由CPU中的指令计数器EIP所指向的,所以在代码段中。因此,i386CPU使用代码段寄存器CS的当前值作为段式映射的选择子,也就是用它作为在段描述表的下标。那么CS的值是多少呢?用GDB调试下test:(gdb)inforeg可以看到CS的值为0x23,我们把它分解成二进制:0000000000100011最低2位为3,说明RPL的值为3,因为这个程序本身就是在用户空间,RPL的值自然为3.第3位为0表示这个下标在GDT中。一、进程虚拟存储空间的管理2、进程虚拟空间的管理一、进程虚拟存储空间的管理3、进程的虚存区域一个4GB空间的页表将占用4MB的物理内存,这样系统开销较大,于是采用虚存段(virtualmemoryarea,vma)及链表来表示一个进程实际用到的虚拟地址空间。一个vma是虚存空间中一个连续的区域,在这个区域中的信息具有相同的操作和访问特性。每个vma段用一个vm_area_struct结构体进行描述.它定义在/include/linux/mm.h中。一、进程虚拟存储空间的管理3、进程的虚存区域进程通常占用几个vma,分别用于代码段、数据段、堆栈段等。在Linux中对vma是如下管理的,当创建一个进程时,系统便为其建立了一个PCB,称为task_struct结构。在这个结构中内嵌了一个包含此进程存储管理有关信息的mm_struct结构,它被用来描述一个进程的虚拟内存的总情况。每一个进程,用一个mm_struct结构体来定义它的虚存用户区(mm_struct是对整个用户空间的描述),记录着用户区内代码段数据段有关数据结构所在的位置以及虚拟内存的其它属性。mm_struct结构体首地址在任务结构体task_struct成员项mm中,mm_struct结构定义在/include/linux/schedul.h中。一、进程虚拟存储空间的管理structmm_struct{–Intcount;/*共享进程数*/–Pdg_t*pgd;/*进程页目录表*/–Unsignedlongcontext;/*进程上下文地址*/–Unsignedlongstart_code,end_code,start_data,end_data;–/*代码段、数据段的首、终地址*/–Unsignedlongstart_brk,brk,start_stack,start_mmap;/*start_stack堆栈首地址*/–Unsignedlongarg_start,arg_end,env_start,env_end;–/*参数区、环境变量去的首、终地址*/–Unsignedlongrss,total_vm,locked_v