物理内存的管理  

  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. FOJ 2013 11 月赛

    这套题目还是比较吊的,由于我的沙茶,还是很多没有做出来- -! C:逆序数 D:呵呵 A:妈蛋,自己精度没弄好,想到之前GCC的要加eps,就WA了几次后交Visual C++过了!C(n,m)p^m ...

  2. C++Builder加载Png图片

    有两种方法,一是把该对象的Transparent 的属性设为true,图片的白色代表即为父界面的颜色 而是在头文件加上#include <pngimage.hpp> Image1-> ...

  3. C#: MessageBox

    系统学习下Form里用到最多的MessageBox MessageBox有21个重载的Show函数...都是返回DialogResult public enum DialogResult { None ...

  4. (转)SQL Server 2005 中的计算字段

    在实际工作上遇到的问题: 在订单表中有某项商品是将“订购数量(Quantity)”乘以“单件价格(UnitCost)”等于该项商品的总价(Subtotal). 在数据表中有的列(以下皆改叫为“字段”) ...

  5. 夺命雷公狗---微信开发17----自定义菜单的事件推送,响应菜单的CLICK

    废话不多说,index.php 代码如下所示: <?php /** * wechat php test */ //define your token require_once "com ...

  6. lower power设计中的DVFS设计

    Pswitch = Ceff * Vvdd^2*Fclk, Pshort-circuit = Isc * Vdd * Fclk, Pleakage = f(Vdd, Vth, W/L) 尽管对电压的s ...

  7. HorizontalScrollView的配置

    package com.exmple.jinritoutiao; import java.util.ArrayList;import java.util.Calendar;import java.ut ...

  8. HorizontalScrollView水平滑动

    xml布局 <HorizontalScrollView            android:id="@+id/hsv"            android:layout_ ...

  9. zabbix监控mysql主从

    最近在公司搭建了zabbix监控系统,现在需要用zabbix来监控mysql的主从同步情况 现在说一下配置的详细步骤: 1.首先给mysql分配一个监控的账号: mysql> grant rep ...

  10. mysql的sql文件的备份与还原

    1.备份 $mysqldump –u root –p*** dbname > filename.sql 2.还原 前提是数据库必须存在 $mysql  –u root –p*** dbname ...