在分析了进程的虚拟地址布局,我们转向内核以及他管理用户内存的机制。下图是gonzo的例子:

Linux进程在内核中是由task_struct进程描述符实现的,task_struct的mm字段指向内存描述符mm_struct,他是进程的一个内存执行摘要。如上图所示,mm_struct存储了内存各个段的开始和结束地址、进程所使用的内存页面数(rss代表常驻集合大小)、使用的虚拟地址空间总数等等。在内存描述符中我们也可以找到两个用于管理进程内层的字段:虚拟内存集合和页表。Gonzo的内存区域如下图:

每个虚拟内存区域(VMA)是一个虚拟地址空间上连续的区域;这些区域不会彼此覆盖。Vm_area_struct结构描述了一个内存区域,包括他的开始和技术地址、flags字段指定了他的行为和访问权限,vm_file字段指定了该区域映射的实际文件。一个没有映射文件的VMA成为匿名的。除了内存映射段以外,上面的每个内存段(堆、栈等等)相当于一个单独的VMA。这不是必须的,尽管在x86机器上通常是这样。VMA不会关心他在哪个段里面。

一个进程的所有VMA以两种方式存储在他的内存描述符中,一种是以链表的方式存放在mmap字段,以开始虚拟地址进行了排序,另一种是以红黑树的方式存放,mm_rb字段为这颗红黑树的根。红黑树可以让内核根据给定的虚拟地址快速地找到内存区域。当我们读取文件/proc/pid_of_process/maps,内核仅仅是通过进程VMA的链接同时打印出每一个。

在windows中,块EPROCESS基本上是task_struct和mm_struct的结合体。Windows用虚拟地址描述符,或者说VAD,模拟一个VMA;VAD存储在一个AVL树(平衡二叉树)中。你知道有关Windows和Linux的最有趣的事情是什么?那就是他们之间差异很小。

4GB大小的虚拟地址空间被分为一个个页面。32位的x86处理器支持的页面大小为4KB、2MB和4MB。Linux和windows都使用4KB大小的页面来映射用户空间部分的虚拟地址空间。0~4095字节为页面0,4096~8191字节为页面1等等。VMA的大小必须是一个页面大小的整数倍。下图是4KB页面大小模式的3GB用户空间:

处理器借助页表将虚拟地址转换为物理地址。每个进程有他自己的页表集合;每当一个进程切换发生,他用户空间的页表也随着切换。Linux在进程的内存描述符中存放了一个pgd字段指向进程的页表。每一个虚拟页面对应与页表中的一个页表入口(PTE),这个入口通常在x86下是一个简单的4字节大小:

Linux有对PTE中每个标志进程读取和设置的函数。标志位P高速处理器虚拟页面在物理内存中是否处于当前。如果清空(等于0),访问该页将触发一个缺页中断。要记住的是当该位为0时,其余的字段都无效。R/W位表示读/写;如果清空,该页为只读。标志位U/S表示用户/管理;如果清空,那么只有内核能够对他进行访问。这些标识用来实现内存的只读以及对内核空间进行保护,就像前面我们说的。

标志位D和A是写脏位和访问控制位。一个脏页是已经被写过的页,而一个被访问的页是已经被写过或者读过的页。这两个标志位的相同点是:处理器只设置他们,而内核负责来清空他们。最后,PTE保存页面的起始物理地址,4KB对齐。这幼稚的前瞻域其实是痛苦的源泉,他限制了可寻址的物理内存为4GB。另一个PTE为的是另一件事情,即PAE。

一个虚拟页面是内存保护的一个单元,因为他的所有字节共享U/S和R/W标志位。不管怎样,带有不用标志位、不同的页面可以映射相同的物理内存。注意在PTE中看不到他的执行权限。这就是经典x86分页允许在栈上执行代码的原因,这样很容易利用栈缓存溢出(当然,也可以利用不可执行栈使用返回到libc或其他技术)。缺少PTE的一个不可执行标志说明了一个广泛的事实:在VMA中的权限标志可能会也可能不会完全转化为硬件保护。内核做了他力所能及的,但是最终体系限制了这种可能。

虚拟内存没有存储任何东西,他只是简单的映射一个程序的地址空间到相关的物理内存,这一大块物理内存叫做物理地址空间。然而在总线上的内存操作多少有些涉及,在这里我们可以忽略并假定物理地址范围从0到最大的可用内存以一个字节的形式增长。物理地址空间被内核分解成一个个页框。处理器不我知道也不关心页框,然而他们对内核来说很关键因为页框是物理内存管理器的单元。在32位模式下linux和windows都使用4KB大小的页框;这里有一个装有2GB RAM机器的例子:

在linux中每个页框由一个描述符和几个标志描述。这些描述符一起跟踪计算机中物理内存入口;每个页框精确的状态总是指到的。物理内存由伙伴内存分配技术管理,如果一个页框能通过伙伴系统分配那么他是空闲的,也就是可分配的。一个分配的页框可能是匿名的,持有程序数据,他可能在页面缓存中,持有的数据存储在一个文件或者块设备中。当然页框还有其他用途,但是我们现在不考虑这些。Windows有一个类似的页框号(PFN)数据库来描述物理内存。

让我们把虚拟内存区、页表入口和页框放在一起来说明这一切是怎么工作的。下面是一个用于堆的例子:

蓝色矩形框代表在VMA区域中的页面,箭头代表页框中映射到页面的页表项。一些虚拟页面没有箭头;这意味着他们对应的PTE的Present标志位为0.这可能是这些页面没有被映射或者他们的内容已经被换出。在任何一种情况下访问这些页面都会导致缺页中断,尽管他们在VMA中。VMA和页表之间的这种关系可能看起来很奇怪,但是这是经常发生的。

VMA就像是一个在你的程序和内核之间的契约。你要求一些事情被处理(内存分配、文件映射等等),内核说:“可以”,并且创建或者更新合适的VMA。但是他实际上并不履行请求权,他会等待指到一个缺页中断发生后才去做实际的工作。内核很懒,就是一个骗人的败类;这是虚拟内存的基本原则。这应用到大多数情形下,一些熟悉的一些令人吃惊的,但是规则是VMA记录达成了什么协议,而PTE反映内核实际做了什么。这两个数据结构一起管理一个程序的内存;包括解决缺页中断、释放内存、换出内存等等。让我们举一个内存分配的简单例子:

当程序通过brk()系统调用申请更多的内存空间时,内核简单地更新堆的VMA。在这一点上,没有页框做实际的分配并且新分配的页面在内存中不是处于当前的。一旦程序进入这些页面,处理器缺页中断发生并且do_page_fault()被调用。他使用find_vma()函数搜索覆盖缺页中断虚拟地址空间的VMA。如果找到,VMA上的权限(读或者写)也会再次被检查。如果没有找到合适的VMA,没有契约覆盖试图进入的内存区,处理器产生段错误。

当找到一个VMA,内核必须查看PTE内容和VMA的类型来处理这个缺页中断,在我们的例子中,PTE显示的页面不是当前的。实际上,我们的PTE是完全空白的(全是0),在linux中意味着虚拟页面没有被映射。一旦这是一个匿名VMA,我们必须由do_anonymous_page()来处理一个纯RAM事务,他分配一个页面帧,用它来映射发生缺页异常的虚拟页面。

事情可能会有些不同。对一个换出页的PTE,例如,Present标志位为0但是整个不是0。他存储持有页面内容的交换位置,这个位置必须用do_swap_page()函数从磁盘上读取加载到一个页面,该函数被一个异常调用。

这里总结了内核的用户内存管理器开始一半,在接下来的文章中,我们把文件加入进来,建立一个完整的内存基础构架图,包括他们实现的性能。

转载于:https://www.cnblogs.com/ngaimaolung/p/3391674.html

Linux教程:内核怎样管理你的内存相关推荐

  1. 尚硅谷linux教程6 组管理和权限管理(难点、重点)

    尚硅谷linux教程6 组管理和权限管理(难点.重点) linux组的基本介绍 在 linux 中的每个用户必须属于一个组,不能独立于组外.在 linux 中每个文件有所有者.所在组.其它组的概念. ...

  2. linux通过内核启动参数预留系统内存

    1 首先正常启动内核 我们需要启动内核后查询一些信息. 2. 查看系统内存信息 内核启动后通过 cat /proc/iomem 查看内存的分布,结果类似: 100000000-10dffffff : ...

  3. Linux内核源码分析之内存管理

    本文站的角度更底层,基本都是从Linux内核出发,会更深入.所以当你都读完,然后再次审视这些功能的实现和设计时,我相信你会有种豁然开朗的感觉. 1.页 内核把物理页作为内存管理的基本单元. 尽管处理器 ...

  4. 【Linux 内核 内存管理】优化内存屏障 ③ ( 编译器屏障 | 禁止 / 开启内核抢占 与 方法保护临界区 | preempt_disable 禁止内核抢占源码 | 开启内核抢占源码 )

    文章目录 一.禁止 / 开启内核抢占 与 方法保护临界区 二.编译器优化屏障 三.preempt_disable 禁止内核抢占 源码 四.preempt_enable 开启内核抢占 源码 一.禁止 / ...

  5. 【Linux 内核】Linux 操作系统结构 ( Linux 内核在操作系统中的层级 | Linux 内核子系统及关系 | 进程调度 | 内存管理 | 虚拟文件系统 | 网络管理 | 进程间通信 )

    文章目录 一.Linux 内核在操作系统中的层级 二.Linux 内核子系统 三.Linux 内核子系统之间的关系 一.Linux 内核在操作系统中的层级 Linux 内核 所在层级 : 整个计算机系 ...

  6. 红黑树在linux内核中的应用场景(红黑树,进程管理CFS,内存管理)丨epoll丨c/c++linux服务器开发丨linux后台开发

    红黑树在linux内核中的应用场景(红黑树,进程管理CFS,内存管理) 视频讲解如下: 红黑树在linux内核中的应用场景(红黑树,进程管理CFS,内存管理)丨epoll丨c/c++linux服务器开 ...

  7. Linux内核机制总结内存管理之连续内存分配器(二十七)

    文章目录 1 连续内存分配器 1.1 使用方法 1.2 技术原理 重要:本系列文章内容摘自<Linux内核深度解析>基于ARM64架构的Linux4.x内核一书,作者余华兵.系列文章主要用 ...

  8. 【Linux 内核 内存管理】优化内存屏障 ④ ( 处理器内存屏障 | 八种处理器内存屏障 | 通用内存屏障 | 写内存屏障 | 读内存屏障 | 数据依赖屏障 | 强制性内存屏障 |SMP内存屏障 )

    文章目录 一.处理器内存屏障 二.Linux 内核处理器内存屏障 一.处理器内存屏障 " 处理器内存屏障 " 针对 " CPU " 之间的内存访问乱序 和 CP ...

  9. 【Linux 内核 内存管理】优化内存屏障 ② ( 内存屏障 | 编译器屏障 | 处理器内存屏障 | 内存映射 I/O 写屏障 )

    文章目录 一.内存屏障 二.编译器屏障 三.处理器内存屏障 一.内存屏障 内存屏障 , 又称为 " 屏障指令 " , 用于保证 " 编译器 " 或 " ...

最新文章

  1. CentOS-7.0的核心安装与配置的补全
  2. oracle所有的乱码解决方案
  3. 《Java编程艺术》目录
  4. P5127-子异和【线段树,树链剖分,位运算】
  5. idea添加jboss_如何将云持久存储添加到JBoss Cool Store
  6. 在OpenShift上将JMS与JBoss A-MQ结合使用。 从远程客户端和加密中学到的经验教训。...
  7. pytorch基础一:张量
  8. 2021中国音乐市场年度综合分析
  9. 【个人笔记】Ubuntu18.04 安装显卡驱动
  10. 如何打造成功的数据归档策略
  11. python计算平均数、众数、中位数、极差、方差、标准差……
  12. 《SuperMap iDesktop的理论知识》
  13. VMware copy之后,如何查看网卡地址 HWADDR
  14. 服务器打开xlsm文件,XLSM 文件扩展名: 它是什么以及如何打开它?
  15. 刚工作2年时15k运维工程师-简历
  16. cad卸载工具_CAD安装失败都是红?
  17. 服装管理系统大一c语言
  18. GAN(生成对抗网络)在合成时间序列数据中的应用(第二部分——利用GAN生成时间序列数据)
  19. xp显示rpc服务器不可用,绿茶XP系统提示“RPC服务器不可用”如何解决
  20. unity-材质球受击变色管理

热门文章

  1. 唐僧肉长生不老到底隐藏了哪些骗局?唐僧的妈妈真的吃过唐僧肉吗?
  2. centos安装 TA-Lib
  3. 让CMD窗口显示中文[JAVAC输出中文错误信息乱码的解决]
  4. ORACLE TEXT LEXER PREFERENCE(四)
  5. [考试反思]0819NOIP模拟测试26:荒芜
  6. linux uname 命令 打印系统信息
  7. 理解动态语言inline cache优化
  8. nodejs + Mysql 在前端页面控制后台数据
  9. BZOJ 3237: [Ahoi2013]连通图
  10. Hdu1232 畅通工程 【并查集】