3.1 概述

  内存管理涵盖了许多领域:

  • 内存中物理内存页的管理;
  • 分配大块内存的伙伴系统;
  • 分配小块内存的slab、slub、slob分配器;
  • 分配非连续内存块的vmalloc机制;
  • 进程的地址空间。

  Linux内核一般将虚拟地址空间划分为两部分:底部较大的部分用于用户进程,顶部则用于内核。虽然(在两个用户进程之间)上下文切换期间会改变下半部分,但是虚拟地址空间的内核部分中总是不变【这其实很好理解,内核是系统管理员,不能说因为每换一批游客,景区管理员都得跟着换一批?!】。在IA-32系统上,虚拟地址空间在用户进程和内核之间划分的典型比例是3:1【arm亦是如此,但是我们使用的mips是2:2的划分。为什么这么划分呢?不解。】。通过修改配置选项可以改变比例,但是只有对非常特殊的配置和应用程序,这种修改才会带来好处。

  可用的物理内存将映射到内核的地址空间中【为什么呢?因为物理内存是内核来管理的,用户空间申请内存必然要通过kernel的分配】。访问内存时,如果所用的虚拟地址空间地址与内核区域的起始地址之间的偏移量不超出物理内存的长度,那么该虚拟地址会自动关联到物理页帧【例如在IA-32系统上,内核的虚拟地址空间只有1GB,但是如果物理内存的大小小于1GB,那么直接线性映射就可以】。不管还有一个问题,如我们所知,在IA-32位系统,大部分人会装4G内存,那么内核如何用1G的虚拟地址空间来管理者4G内存呢?如果物理内存比可以映射到内核地址空间中的数量要多,那么必须借助高端内存(highmem)方法来管理“多余的内存”。在IA-32系统上,可以直接管理的物理内存数量不超过896MB。超过该值的内存只能通过高端内存寻址【为什么是896?!满足两个约束条件:1.直接映射的内存尽量多 2.剩余的虚拟地址空间足够管理多余的内存】。

  主:1. 内核使用高端内存之前,必须使用kmap和kunmap函数将其映射到内核虚拟地址空间中,对普通内存这是不必要的。因为普通内存和内核虚拟地址空间存在线性映射关系,但是高端内存必须在使用时临时建立映射。所以访问普通内存要比高端内存块。

    2. 对用户进程来说,是高端内存还是普通页完全没有任何差别。因为用户空间总是通过页表访问内存,绝不会直接访问。

  有两种不同的计算机,分别以不同的方法管理内存。

  (1)UMA计算机(一致内存访问,uniform memory access)将可用内存以连续的方式组织起来(可能有小缺口)。SMP系统中每个处理器访问各个内存区一样快。

  (2)NUMA计算机(非一致内存访问,non-uniform memory access)总是多处理器的计算机。系统的各个CPU都有本地内存,可支持特别快速的访问。各个处理器之间通过总线连接起来,以支持对其他CPU的本地内存访问,当然比访问本地内存慢些。

                UMA系统

              NUMA系统

  两种类型计算机的混合也是可能的,其中使用不连续的内存。即在UMA系统中,内存不是连续的,而有比较大的洞。此时使用NUMA体系结构的原理可以使内核的内存访问更简单。实际上内核会区分3中配置选项:FLATMEM、DISCONTIGMEM和SPARSEMEM。DISCONTIGMEM和SPARSEMEM实际作用相同,但从开发者的角度讲,对应代码的质量有所不同。SPARSMEM被认为更多是实验性的,不那么稳定,但有一些性能优化。我们认为DISCONTIGMEM相关代码更稳定一些,但不具备内存热拔插之类的新特性。

    FLATMEM是内核的默认配置,也是使用最多的内存组织类型。我们主要讨论FLATMEM。

  真正的NUMA会配置选项CONFIG_NUMA,相关内存管理的代码与上述两种变体有所不同。通过配置NUMA_EMU可以使用平坦内存模型的AMD64系统来感受NUMA系统的复杂性,实际上将内存划分为加的NUMA内存域。由于某种原因,NUMA计算机过于昂贵。

  我们集中讨论UMA系统,不考虑OCNFIG_NUMA。由于UMA系统可以在地址空间有比较大的洞是选择配置选项CONFIG_DISCONTIGMEM,这种情况下即使不采用NUMA技术但是系统也会有多个内存结点。所以NUMA相关的数据结构不可完全忽略。

  注意:在下文中,我们经常会用到术语分配阶(allocation order)。它表示内存区中页的数目以2为底的对数。阶0的分配由一个页面组成,阶1的分配包括2^1 = 2个页。

【深入理解Linux内核架构】第3章:内存管理的更多相关文章

  1. 《深入理解linux内核架构》第二章 进程管理和调度

    2.1进程优先级 进程优先级 硬实时进程 软实时进程 抢占式多任务处理 2.2进程生命周期 用户太切换到核心态的办法 系统调用 中断 抢占调度模型优先级普通进程<系统调用<中断 普通进程可 ...

  2. 十天学Linux内核之第三天---内存管理方式

    原文:十天学Linux内核之第三天---内存管理方式 昨天分析的进程的代码让自己还在头昏目眩,脑子中这几天都是关于Linux内核的,对于自己出现的一些问题我会继续改正,希望和大家好好分享,共同进步.今 ...

  3. 【深入理解Linux内核架构】3.3 页表

    页表:用于建立用户进程空间的虚拟地址空间和系统物理内存(内存.页帧)之间的关联. 向每个进程提供一致的虚拟地址空间. 将虚拟内存页映射到物理内存,因而支持共享内存的实现. 可以在不增加物理内存的情况下 ...

  4. 【深入理解Linux内核架构】3.2 (N)UMA模型中的内存组织

    内核对一致和非一致内存访问系统使用相同的数据结构.在UMA系统上,只使用一个NUMA结点来管理整个系统内存.而内存管理的其他部分则相信他们是在处理一个伪NUMA系统. 3.2.1 概述 内存划分为结点 ...

  5. Linux内核分析——第三章 进程管理

    第三章 进程管理 3.1 进程 1.进程就是处于执行期的程序:进程就是正在执行的程序代码的实时结果:进程是处于执行期的程序以及相关的资源的总称:进程包括代码段和其他资源. 线程:是在进程中活动的对象. ...

  6. 《Linux内核设计与实现》内存管理札记

    1.页 芯作为物理页存储器管理的基本单元,MMU(内存管理单元)中的页表,从虚拟内存的角度来看,页就是最小单位. 内核用struct page结构来标识系统中的每个物理页.它的定义例如以下: flag ...

  7. 【深入理解Linux内核架构】6.6 资源分配

    一段摘自<Linux设备驱动程序>的话: 每种外设都通过读写寄存器进行控制.大部分外设都有多个寄存器,不管是内存地址空间还是I/O地址空间,这些寄存器的访问地址都是连续的. 在硬件层,内存 ...

  8. [Wolfgang Mauerer] 深入linux 内核架构 第十三章 系统调用

    作为Linux开发爱好者,从事linux 开发有三年多时间.做过bsp移植,熟悉u-boot代码执行流程:看过几遍<linux 设备驱动程序开发>,分析过kernel启动流程,写过驱动,分 ...

  9. 《深入理解linux内核》第三章 进程

    进程的七种状态 在内核源码的 include/linux/sched.h文件中: task_struct的status可表示 #define TASK_RUNNING 0 #define TASK_I ...

随机推荐

  1. springboot中RedisTemplate的使用

    springboot中RedisTemplate的使用 参考 了解 Redis 并在 Spring Boot 项目中使用 Redis--以IBM为学习模板 springboot之使用redistemp ...

  2. 关于C#调用非托管DLL,报“内存已损坏的”坑,坑,坑

    因客户需求,与第三方对接,调用非托管DLL,之前正常对接的程序,却总是报“内存已损坏的异常”,程序进程直接死掉,折腾到这个点(2018-05-11 00:26),终于尘埃落定,直接上程序. 之前的程序 ...

  3. Java多线程_缓存对齐

    1.什么是缓存对齐 当前的电脑中,数据存储在磁盘上,可以断电保存,但是读取效率较低.不断电的情况下,数据可以在内存中存储,相对硬盘效率差不多是磁盘的一万倍左右.但是运算时,速度最快的是直接缓存在CPU ...

  4. 更换IntelliJ Idea的Terminal为git_home/bin/sh.exe命令端程序

    idea中默认的terminal形式: 1.在IDEA中,打开settings,设置相应的bash路径 settings–>Tools–>Terminal–>Shell path:C ...

  5. RSA非对称加密(java实例代码)

    使用RSA对WebService传递的信息加密解密的基本思想是:服务器端提供一个WebService方法String getServerPublicKey(),客户端可以以此得到服务器端的公钥,然后使 ...

  6. 手写Promise简易版

    话不多说,直接上代码 通过ES5的模块化封装,向外暴露一个属性 (function(window){ const PENDING = 'pending'; const RESOLVED = 'fulf ...

  7. 类的加载,链接和初始化——1运行时常量池(来自于java虚拟机规范英文版本+本人的翻译和理解)

    加载(loading):通过一个特定的名字,找到类或接口的二进制表示,并通过这个二进制表示创建一个类或接口的过程. 链接:是获取类或接口并把它结合到JVM的运行时状态中,以让类或接口可以被执行 初始化 ...

  8. Fiddler添加显示ip和响应时间

    1. 打开Fiddler,在菜单Rules 栏里点击Customize Rules…或者使用快捷键CTRL+R打开Fiddler ScriptEditor 图 1 Customize Rules 2. ...

  9. JS 替换日期的横杠为斜杠

    例如1: <script type="text/javascript">      var dt = "2010-01-05";           ...

  10. 一文教你读懂JVM类加载机制

    Java运行程序又被称为WORA(Write Once Run Anywhere,在任何地方运行只需写入一次),意味着我们程序员小哥哥可以在任何一个系统上开发Java程序,但是却可以在所有系统上畅通运 ...