作者:Dong | 可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明 网址:http://dongxicheng.org/os/linux-memory-management-basic/ 1. 基本概念 1.1 地址 (1)逻辑地址:指由程序产生的与段相关的偏移地址部分。在C语言指针中,读取指针变量本身值(&操作),实际上这个值就是逻辑地址,它是相对于你当前进程数据段的地址。 (2)线性地址:段中的偏移地址(逻辑地址),加上相应段的基地址就生成了一个线性地址。 (3)物理地址: 放在寻址总线上的地址。 (4)虚拟地址:保护模式下段和段内偏移量组成的地址,而逻辑地址就是代码段内偏移量,或称进程的逻辑地址。 1.2 内存 (1) 虚拟内存:计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。与没有使用虚拟内存技术的系统相比,使用这种技术的系统使得大型程序的编写变得更容易,对真正的物理内存(例如RAM)的使用也更有效率。 (2) 物理内存:实际的内存。物理地址被分成离散的单元,成为页(page)。目前大多数系统的页面大小都为4k。 1.3 地址转换 Linux采用段页式管理机制,有两个部件用于地址转换:分段部件和分页部件。 (1) 分段部件:将逻辑地址转换为线性地址。分段提供了隔绝各个代码、数据和堆栈区域的机制,因此多个程序(任务)可以运行在同一个处理器上而不会互相干扰。 (2) 分页部件:将线性地址转换为物理地址(页表和页目录),若没有启用分页机制,那么线性地址直接就是物理地址。 ![]() 2. 内存分配 Malloc,kmalloc 和vmalloc区别? (1) kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存。 (2) kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续。 (3) kmalloc申请的内存比较小,一般小于128 K。它是基于slab(内存池)的,以加快小内存申请效率。 3. 常见问题 (1) 调用malloc函数后,OS会马上分配实际的内存空间吗? 答:不会,只会返回一个虚拟地址,待用户要使用内存时,OS会发出一个缺页中断,此时,内存管理模块才会为程序分配真正的内存。 (2) 段式管理和页式管理的优缺点? 在段式存储管理中,将程序的地址空间划分为若干个段(segment),这样每个进程有一个二维的地址空间,相互独立,互不干扰。程序通过分段划分为多个模块,如代码段、数据段、共享段。这样做的优点是:可以分别编写和编译源程序的一个文件,并且可以针对不同类型的段采取不同的保护,也可以按段为单位来进行共享。段式存储管理的优点是:没有内碎片,外碎片可以通过内存紧缩来消除;便于实现内存共享。 在页式存储管理中,将程序的逻辑地址空间划分为固定大小的页(page),而物理内存划分为同样大小的页框(pageframe)。程序加载时,可将任意一页放人内存中任意一个页框,这些页框不必连续,从而实现了离散分配。这种管理方式的优点是,没有外碎片,且一个程序不必连续存放。这样就便于改变程序占用空间的大小。 页式和段式系统有许多相似之处。比如,两者都采用离散分配方式,且都通过地址映射机构来实现地址变换。但概念上两者也有很多区别,主要表现在: [1] 页是信息的物理单位,分页是为了实现离散分配方式,以减少内存的外零头,提高内存的利用率。或者说,分页仅仅是由于系统管理的需要,而不是用户的需要。段是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了更好地满足用户的需要。 [2] 页的大小固定且由系统决定,把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的。段的长度不固定,且决定于用户所编写的程序,通常由编译系统在对源程序进行编译时根据信息的性质来划分。 [3] 页式系统地址空间是一维的,即单一的线性地址空间,程序员只需利用一个标识符,即可表示一个地址。分段的作业地址空间是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。 (3) Malloc在什么情况下调用mmap? 从操作系统角度来看,进程分配内存有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)。brk是将数据段(.data)的最高地址指针_edata往高地址推,mmap是在进程的虚拟地址空间中(一般是堆和栈中间)找一块空闲的。这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。 在标准C库中,提供了malloc/free函数分配释放内存,这两个函数底层是由brk,mmap,munmap这些系统调用实现的。 默认情况下,malloc函数分配内存,如果请求内存大于128K(可由M_MMAP_THRESHOLD选项调节),那就不是去推_edata指针了,而是利用mmap系统调用,从堆和栈的中间分配一块虚拟内存。这样子做主要是因为brk分配的内存需要等到高地址内存释放以后才能释放(例如,在B释放之前,A是不可能释放的),而mmap分配的内存可以单独释放。 (4) 32位系统,通常情况下,最大虚拟地址和物理地址空间为多少? 不使用PAE情况下,最大虚拟地址和物理地址空间均为4G,若果使用PAE,最大虚拟地址仍为4G,而物理地址空间可变为64G(x86, 32为变36位)。 (5) 怎样实现malloc和free? Malloc实现可考虑采用buddy算法+slob算法,free类似。 4. 参考资料 Linux Memory Management Notes: http://vmlinz.is-programmer.com/posts/26540.html 内存段页式管理笔记: http://chenxu.yo2.cn/articles/linux_memory.html 虚拟地址、线性地址和物理地址的转换: http://dogking.chinaunix.com/space.php?uid=23208702&do=blog&id=163527 kmalloc、vmalloc、malloc的区别: http://blog.csdn.net/macrossdzh/article/details/5958368 Linux中的物理和虚拟存储空间布局: http://book.chinaunix.net/showart.php?id=3266 [百度分享]频繁分配释放内存导致的性能问题的分析 http://topic.csdn.net/u/20100325/16/0b86c0ed-5b8d-4eec-a757-c782ae9a3a35.html 5. 后记 最近面试常被问到内存管理的一些基础知识,特整理此文,以作为这阶段面试的小总结。 原创文章,转载请注明: 转载自董的博客 本文链接地址: http://dongxicheng.org/os/linux-memory-management-basic/ |
Linux内存管理基本概念
最新推荐文章于 2024-05-18 09:40:56 发布