物理内存的管理  

  Linux管理物理内存是使用分页机制实现的。为了使分页机制在32位和64位体系结构下高效工作,Linux采用了一个四级分页策略

  Linux支持多种内存分配机制。分配物理内存页框的主要机制是页面分配器,它使用了著名的伙伴算法作为物理内存分配机制。

  管理一块内存的基本思想如下。刚开始,内存由一块连续的片段组成,下图的简单例子是64个页面。当一个内存请求到达时,首先向上舍入到2的幂,比如8个页面。然后整个内存被分割成两半,如图b所示。因为这些片段还是太大了,较低的片段被再次二分(c),然后再二分(d)。现在我们有一块大小合适的内存,因此把它分配给请求者,如图d所示。

  

  现在假定8个页面的第二个请求到达了。这个请求有(e)直接满足了。此时4个页面的第三个请求到达了。最小可用的块被分割(f),然后其一半被分配(g)。接下来,8页面里的第二个块碑释放(h)。最后,8页面的另一个块也被释放。因为刚刚释放的两个邻接的8页面块来自同一个16页面块,它们合并起来得到一个16页面的块(i)。

虚拟地址空间 

  Linux为每个进程维持一个单独的虚拟地址空间。如下图所示。

  

  

  虚拟地址空间被分割成同构连续页面对齐的区域。也就是说,每个区域由一系列连续的具有相同保护和分页属性的页面组成。代码段、数据段、堆、共享库段以及用户栈都是不同的区域。每个存在的虚拟页面都保存在某个区域中,而不属于某个区域的虚拟也是不存在的。在虚拟地址空间的区之间可以有空隙。所有对这些空隙的引用都会导致一个严重的页面故障。

  在内核中,每个区是用vm_area_struct项来描述的。一个进程的所有vm_area_struct用一个链表连接在一起,并且按照虚拟地址排序以便可以找到所有的页面。当这个链表太长时(多于32项),就创建一个树来加速搜索。vm_area_struct项列出了该区的属性。这些属性包括:保护模式(如,只读或者可读可写),是否固定在内存中(不可换出)、朝向哪个方向生长(数据段向上,栈段向下)。

  vm_area_struct也记录了该区是私有的还是跟一个或多个其他进程共享的。fork之后,Linux为子进程复制一份区链表,但是为了让父子进程指向相同的也表。区标记为可读可写,但是页面却被标记为只读。如果任何一个进程试图写页面,就会产生一个保护故障,此时内核发现该内存区域逻辑上是可写的,但是页面却不是,因此它把该页面的一个副本给当前进程同时标记为可读可写。这个机制就说明了写时复制是如何实现的。

  vm_area_struct也记录了该区是否在磁盘上有备份存储,如果有,在什么地方。代码段把可执行二进制文件作为备份存储,内存映射文件把磁盘文件作为备份存储。其他区,如栈,直到它们不得不被换出,否则没有备份存储被分配。

  一个顶层内存描述符mm_struct收集属于一个地址空间的所有虚拟内存区相关的信息,还有关于不同段(代码、数据、栈)和用户共享地址空间的信息等。一个地址空间的所有vm_area_struct元素可以通过内存描述符用两种方式访问。首先,它们是按照虚拟地址顺序组织在链表中的。这种方式的有用之处是:当所有的虚拟地址区需要被访问时,或者当内核查找分配一个指定大小的虚拟内存区域时。此外,vm_area_struct项目被组织成二叉“红黑”树。这种方法用于访问一个指定的虚拟内存地址。为了能够用这两种方法访问进程地址空间的元素,Linux为每个进程使用了更多的状态,但是却允许不同的内核操作来使用这些访问状态,这对进程而言更加高效。

  下图强调了记录一个进程中虚拟存储器区域的内核数据结构。内核为系统中的每个进程维护一个单独的任务结构(源代码中的task_struct)。任务结构中的元素包含或者指向内核运行该进程所需要的所有信息(例如,PID,指向用户栈的指针、可执行目标文件的名字以及程序计数器)。

  

  task_struct中的一个条目指向mm_struct,它描述了虚拟存储器的当前状态。我们感兴趣的两个字段是pdg和mmap,其中pdf指向第一级页表(页全局目录)的基址,而mmap指向一个vm_area_struct(区域结构链表),其中每个vm_area_strcuts都描述了当前虚拟地址空间的一个区域(area)。当内核运行这个进程时,它就将pdf存放在CR3控制寄存器中。

  为了我们的目的,一个具体区域的区域结构包含下面的字段:

  vm_struct:指向这个区域的起始处。

  vm_end: 指向这个区域的结束处。

  vm_prot: 描述这个区域内包含的所有页的读写许可权限。

  vm_flags:描述这个区域内的页面是与其他进程共享的,还是这个进程私有的、

  vm_next: 指向链表中下一个区域结构。

虚拟地址空间到物理地址空间的映射

  虚拟存储的实现需要依靠硬件的支持,对于不同的CPU来说是不同的。但是几乎所有的硬件都采用一个MMU((Memmory Management Unit)的部件来进行映射,如下图所示。

  

  在页映射模式下,CPU发出的是Virtual Address, 即我们的程序看到的是虚拟地址。经过MMU转换以后就变成了Physical Address。一般MMU都集成在CPU内部了,不会以独立的部件存在。

参考资料:

  1. 《深入理解计算机系统》 (第二版)  机械工业出版社

  2. 《程序员的自我修养》

  3. 《现代操作系统》(原书第2版)  机械工业出版社

Linux是如何管理内存的的更多相关文章

  1. 性能测试必备知识(10)- Linux 是怎么管理内存的?

    做性能测试的必备知识系列,可以看下面链接的文章哦 https://www.cnblogs.com/poloyy/category/1806772.html 内存映射 日常生活常说的内存是什么 比方说, ...

  2. linux内核分析之内存管理

    1.struct page /* Each physical page in the system has a struct page associated with * it to keep tra ...

  3. 初探Linux内核中的内存管理

    Linux内核设计与实现之内存管理的读书笔记 初探Linux内核管理 内核本身不像用户空间那样奢侈的使用内存; 内核不支持简单快捷的内存分配机制, 用户空间支持? 这种简单快捷的内存分配机制是什么呢? ...

  4. [转载]linux段页式内存管理技术

    原始博客地址: http://blog.csdn.net/qq_26626709/article/details/52742470 一.概述 1.虚拟地址空间 内存是通过指针寻址的,因而CPU的字长决 ...

  5. Linux的虚拟内存管理-如何分配和释放内存,以提高服务器在高并发情况下的性能,从而降低了系统的负载

    Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...

  6. Linux系统基本的内存管理知识讲解

    内存是Linux内核所管理的最重要的资源之一.内存管理系统是操作系统中最为重要的部分,因为系统的物理内存总是少于系统所需要的内存数量.虚拟内存就是为了克服这个矛盾而采用的策略.系统的虚拟内存通过在各个 ...

  7. <Linux内核源码>内存管理模型

    题外语:本人对linux内核的了解尚浅,如果有差池欢迎指正,也欢迎提问交流! 首先要理解一下每一个进程是如何维护自己独立的寻址空间的,我的电脑里呢是8G内存空间.了解过的朋友应该都知道这是虚拟内存技术 ...

  8. [内存管理]linux X86_64处理器的内存布局图

    linux X86 64位内存布局图

  9. java语言:Linux与JVM的内存关系分

    在一些物理内存为8g的服务器上,主要运行一个Java服务,系统内存分配如下:Java服务的JVM堆大小设置为6g,一个监控进程占用大约 600m,Linux自身使用大约800m.从表面上,物理内存应该 ...

随机推荐

  1. Oracle-数据库

    Oracle 1.特点 关系型数据库 采用二维表的行使管理数据库 具有行和列  表间存在关联关系 2.安装 数据库(11g) 版本类型 32位    64位  安装类型 桌面类 本机开发 服务器类 生 ...

  2. codeforces-Glass Carving(527C)std::set用法

    C. Glass Carving time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  3. .NET: WPF Template

    Data Template: 要做一个listBox,里面有车子的简单信息,点了里面的item后就会显示详细信息. car class: using System; using System.Coll ...

  4. UML:包图

    什么是包图?包图是对UML图进行“打包”,按照你期望的方式进行组织的一种图.包图用于展示宏观上的内容.往往利用包图对类进行“打包”,但包图其实可以对任何UML图进行“打包”.包图是逻辑上的概念,你可以 ...

  5. Apache与Nginx虚拟主机设置(多域名和多端口的区别)

    为了方便管理虚拟主机,应该尽量少修改主配置文件http.conf或者nginx.conf,大部分修改变更都在虚拟主机片配置文件httpd- vhost.conf或者vhost.conf中完成,这样有利 ...

  6. 变形--扭曲 skew()

    变形--扭曲 skew() 扭曲skew()函数能够让元素倾斜显示.它可以将一个对象以其中心位置围绕着X轴和Y轴按照一定的角度倾斜.这与rotate()函数的旋转不同,rotate()函数只是旋转,而 ...

  7. 2013年各大小IT公司待遇

    2013年各大小IT公司待遇(初版   摘自好网)本人西电硕士,根据今年找工作的情况以及身边同学的汇总,总结各大公司的待遇如下,吐血奉献给各位学弟学妹,公司比较全,你想去的公司不在这里面,基本上是无名 ...

  8. linux挂接U盘

    挂接U盘fdisk -lDisk /dev/sdd: 131 MB, 131072000 bytes/dev/sdd1 * 1 889 127983+ b Win95 FAT32#mkdir -p / ...

  9. android fragment+ FragmentTabHost+viewpager 切换状态不保存的问题

    转载请注明出处:http://blog.csdn.net/djy1992/article/details/46674169 @author dujinyang 难得有时间上来写博客. fragment ...

  10. 写sql语句分别按日,星期,月,季度,年统计

    --写sql语句分别按日,星期,月,季度,年统计销售额 --按日 ' group by day([date]) --按周quarter ' group by datename(week,[date]) ...