资源预览内容
第1页 / 共27页
第2页 / 共27页
第3页 / 共27页
第4页 / 共27页
第5页 / 共27页
第6页 / 共27页
第7页 / 共27页
第8页 / 共27页
第9页 / 共27页
第10页 / 共27页
亲,该文档总共27页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
嵌入式Linux操作系统 第4章 存储管理,www.embedu.org,2,第1章 嵌入式Linux操作系统简介 第2章 Linux操作系统使用与系统配置 第3章 嵌入式Linux编程环境 第4章 存储管理 第5章 操作系统进程 第6章 进程间通信 第7章 中断与系统调用 第8章 文件管理 第9章 设备管理 第10章 嵌入式Linux的构建,课程安排:,www.embedu.org,3,第4章 存储管理 4.1 进程虚存空间的管理 4.2 内存空间/地址类型 4.3 分页机制与MMU 4.4 高速缓存 4.5 内存区域Zone 4.6 获得内存页面 4.7 slab分配器 4.8 kmalloc 4.9 高端内存 4.10 虚拟内存的申请和释放 思考题,本章课程:,www.embedu.org,4,4.1 进程虚存空间的管理,Linux运行在x86架构时,进程的虚拟内存为4GB。进程虚存空间的划分在系统初始化时由GDT确定,它定义在/arch/i386/kernel/head.S文件中: .quad 0x0000000000000000 /* NULL 描述符 */ .quad 0x0000000000000000 /* 未使用*/ .quad 0xc0c39a000000ffff /* 内核代码段1GB在0xc0000000 */ .quad 0xc0c392000000ffff /* 内核数据段1GB在0xc0000000 */ .quad 0x00cbfa000000ffff /* 用户代码段3GB在0x00000000 */ .quad 0x00cbf2000000ffff /* 用户数据段3GB在0x00000000 */ .quad 0x0000000000000000 /* 未使用 */ .quad 0x0000000000000000 /* 未使用 */ .fill 2*NR_TASKS,8,0 /* 各个进程LDT描述符和TSS描述符的空间 */ Linux的存储管理主要是管理进程虚拟内存的用户区。进程虚拟内存的用户区分成代码段、数据段、堆栈以及进程运行的环境变量、参数传递区域等。每一个进程都用一个mm_struct结构体来定义它的虚存用户区。mm_struct结构体首地址在任务结构体task_struct成员项mm中。,www.embedu.org,5,4.1 进程虚存空间的管理,4.1.1 进程的虚存区域 一个虚存区域是虚存空间中一个连续的区域,在这个区域中的信息具有相同的作和访问特性。每个虚拟区域用一个vm_area_struct结构体进行描述.它定义在/include/linux/mm.h中,www.embedu.org,6,4.1 进程虚存空间的管理,4.1.2 虚存空间的映射和虚存区域的建立 虚拟内存使计算机可以操纵更大的地址空间,还可以使系统中的每一个进程都有自己的虚拟地址空间。这些虚拟的地址空间是相互完全分离的,所以运行一个应用程序的进程不会影响另外的进程。另外,硬件的虚拟内存机制允许对内存区写保护。这可以防止代码和数据被错误的程序覆盖。 内存映射可以将CPU的虚拟地址空间映射到系统的物理内存。 核心的共享虚拟内存机制,虽然允许进程拥有分离(虚拟)的地址空间,但有时也需要进程之间共享内存。例如,系统中可能有多个进程运行命令解释程序bash 。尽管可以在每一个进程的虚拟地址空间都拥有一份 bash 的拷贝,但更好的方法是在物理内存中只拥有一份拷贝,所有运行 bash 的进程共享代码。动态连接库是多个进程共享执行代码的另一个常见例子。另外,共享内存也经常用于进程间通讯机制,两个或多个进程可以通过共同拥有的内存交换信息。Linux系统支持系统V的共享内存 IPC机制。 Linux虚存采用动态地址映射方式,即进程的地址空间和存储空间的对应关系是在程序的执行过程中实现的。进程使用的是虚拟地址,因此它对每个地址的访问都需通过MMU把虚拟地址转化为内存的物理地址。,www.embedu.org,7,4.1 进程虚存空间的管理,4.1.2 虚存空间的映射和虚存区域的建立 动态地址映射使Linux可以实现进程在主存中的动态重定位,虚存段的动态扩展和移动,也为虚存的实现提供了基础。当Linux中的进程映象执行时,需要调入可执行映象的内容。但并不需要把这些数据直接调入物理内存,只需要把这些数据放入该进程的虚拟内存区。只有当在执行需要这些数据时才真正调入内存。这种进程的映象和进程虚拟进程空间的连接叫内存映象。当需要将进程映象调入进程的虚拟内存空间时,需要申请一段合适的虚拟内存空间,在这种情况下需要用到mmap系统调用来获得所需的内存空间。 Linux使用do_mmap()函数完成可执行映像向虚存区域的映射,由它建立有关的虚存区域 do_mmap()函数定义在includelinuxmm.h文件中: static inline unsigned long do_mmap(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flag, unsigned long offset),www.embedu.org,8,4.2 内存空间/地址类型,CPU地址空间(address space)是一段表示内存位置的地址范围。在x86架构下,地址空间有三种:物理地址空间,线性地址空间和逻辑地址空间(虚拟地址空间)。而在ARM体系结构下只有物理地址空间和逻辑地址空间(虚拟地址空间)。 物理地址是一个系统中可用的真实的硬件地址。假如一个系统有128M内存,它的合法地址范围是从0到0x8000000(以十六进制表示)。每个地址都对应于所安装的SIMMs中的一组晶体管,而且对应于处理器地址总线上的一组特定信号 逻辑地址则是CPU所能处理的地址空间的总和,对于32位CPU而言,它的逻辑地址空间是4G.。采用逻辑地址空间的好处是每个用户进程都有自己独立的运行空间,而不用管自己在物理内存的实际位置。在Linux系统中,4G的地址空间由Linux内核与Linux应用程序共同分享。 内核空间与用户空间: 用户空间使用0x00000000-0xBFFFFFFF 3G的地址空间,此空间用户态进程可以直接访问。内核空间则使用0xC0000000-0xFFFFFFFF 剩下的1G地址空间,存放内核访问的代码和数据,用户态进程不能直接访问。用户进程只有通过中断或系统调用进入核心态时才有权利访问。 在逻辑地址和物理地址之间相互转换的工作是CPU的内存管理单元MMU完成的。Linux内核负责告诉MMU如何把逻辑页面映射到物理页面。通常内核需要维护每个进程的逻辑地址和物理地址对照表,在切换进程时,更新MMU的对照表信息。而MMU在进程提出内存请求时会自动完成实际的地址转换工作,www.embedu.org,9,4.2 内存空间/地址类型,在x86体系结构上,把线性地址映射到物理地址分为两个步骤。提供给进程的线性地址被分为三个部分:一个页目录索引,一个页表索引和一个偏移量。页目录(page directory)是一个指向页表的指针数组,页表(page table)是一个指向页面的指针数组,因此地址映射就是一个跟踪指针链的过程。一个页目录能够确定一个页表,继而得到一个页面,然后页面中的偏移量(offset)能够指出该页面里的一个地址。 为了进行更详细因而也会更准确的描述,给定页目录索引中的页目录项保存着贮存在物理内存上的一个页表地址,给定页表索引中的页表项保存着物理内存上相应物理页面的基地址,然后线性地址的偏移量加到这个物理地址上形成最终物理页面内的目的地址。MMU对线性地址的转换如图所示。 MMU线性地址到物理地址转换图:,www.embedu.org,10,4.3 分页机制与MMU,Linux的内存管理采用页式管理,使用多级页表,动态地址转换机构与主存、辅存共同实现虚拟内存。每个用户进程拥有4GB的虚拟地址空间,进程在运行过程中可以动态浮动和扩展,为用户提供了透明的,灵活有效的内存使用方式。这正是进程被分配一个逻辑地址空间的原因之一。即使每个进程有相同的逻辑地址空间,通过分页机制,相应进程的物理地址也都是不同的,因此它们在物理上不会彼此重叠。 从内核的角度看来,逻辑和物理地址都被划分成固定大小的页面。每个合法的逻辑页面恰好处于一个物理页面中,方便MMU的地址转换。当地址转换无法完成时,比如,由于给定的逻辑地址不合法或者由于逻辑页面没有对应的物理页面的时候,MMU产生中断,向核心发出信号。Linux核心可以处理这种页面错误(page fault)问题。 MMU也负责增强内存保护,当一个应用程序试图在它的内存中对一个已标明是只读的页面进行写操作时,MMU也会产生中断错误,通知内核。在没有MMU的情况下,内核不能够防止一个进程非法存取其它进程的内存空间。,www.embedu.org,11,4.3 分页机制与MMU,每个进程都有一套自己的页目录与页表,其中页目录的基地址是关键,通过它才能查到逻辑所对应的物理地址。页目录的基地址是每个进程的私有资源,保存在该进程的task_struct对象的mm_struct结构变量mm中。mm_struct结构在includelinuxmm_types.h中定义。 在进程切换时,cpu会把新进程的页目录基地址填入cpu的页目录寄存器,供MMU使用,当新进程有地址访问时MMU会根据被访问地址的最高十位从页目录中找到对应的页表基地址,然后根据次高十位再从页表中找到对应的物理地址的页首,最后根据剩下的12位偏移量与页首地址找到逻辑地址对应的真正物理地址。在Linux内核中,有关页目录与页表的操作已被定义成一套宏,使用起立非常方便。相关定义都在文件中。,www.embedu.org,12,4.4 高速缓存,1)缓冲区高速缓存 缓冲区高速缓存中包含了被块设备驱动使用的数据缓冲,这些缓冲的单元的大小一般固定(比如512 字节),包含从块设备读出或者写入的信息块。块设备是仅能够以固定大小块进行读写操作的设备。所有的硬盘都是块设备。利用设备标志符和所需块号作索引可以在缓冲区高速缓存中迅速地找到数据块。块设备只能够通过缓冲区高速缓存来存取。如果数据在缓冲区缓存中可以找到,则无需从物理块设备(如硬盘)中读取,这样可以加速设备的访问。 2)页高速缓存 页高速缓存用来加速块设备上可执行映象文件与数据文件的存取。它每次缓冲一个页面的文件内容。页面从块设备上读入内存后缓存在页高速缓存中。 3)交换高速缓存 只有修改过的页面存储在交换文件中。只要这些页面在写入到交换文件后没有被修改则下次此页面被交换出内存时就不必再进行更新写操作这些页面都可以简单的丢弃在交换频繁发生的系统中。交换高速缓存可以省下很多不必要且耗时的块设备操作。 4)硬件高速缓存 一个常见的硬件高速缓存是处理器中的指令和数据cache,它们缓存CPU最近访问过的指令和数据,使CPU不需要到内存中获取数据。实际上它是CPU与内存之间的桥梁。,www.embedu.org,13,4.4 高速缓存,常见的cpu中cache的实现按读写方式分类: 贯穿读出式(Look Through) 该方式将Cache隔在CPU与主存之间,CPU对主存的所有数据请求都首先送到Cache,由Cache自行在自身查找。如果命中,则切断CPU对主存的请求,并将数据送出;不命中,则将数据请求传给主存。该方法的优点是降低了CPU对主存的请求次数,缺点是延迟了CPU对主存的访问时间。 旁路读出式(Look Aside) 在这种方式中,CPU发出数据请求时,并不是单通道地穿过Cache,而是向Cache和主存同时发出请求。由于Cache速度更快,如果命中,则Cache在将数据回送给CPU的同时,还来得及中断CPU对主存的请求;不命中,则Cache不做任何动作,由C
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号