在一个多任务操作系统的每个进程在其自己的沙箱的存储器执行。沙盒是一个虚拟地址空间(virtual address space)。

1 32位虚拟内存布局

在32下部模式虚拟地址空间始终是一个4GB内存地址块。这些虚拟地址的页表(page table)映射到物理内存,页表由操作系统维护并被处理器引用。

每个进程拥有一套属于它自己的页表,可是另一个隐情。

仅仅要虚拟地址被使用,那么它就会作用于这台机器上执行的全部软件。包含内核本身。因此一部分虚拟地址必须保留给内核使用:

图 1

这并不意味着内核使用了那么多的物理内存,仅表示它可支配这么大的地址空间,可依据内核须要。将其映射到物理内存。

内核空间在页表中拥有较高的特权级(ring 2或下面)。因此仅仅要用户态的程序试图訪问这些页,就会导致一个页错误(page fault),用户程序不可訪问内核页。在Linux中,内核空间是持续存在的,而且在全部进程中都映射到相同的物理内存。内核代码和数据总是可寻址的。随时准备处理中断和系统调用。与此相反,用户模式地址空间的映射随进程切换的发生而不断变化:

图 2

图2中,蓝色区域表示映射到物理内存的虚拟地址,而白色区域表示未映射的部分。在上面的样例中,Firefox使用了相当多的虚拟地址空间。由于它是传说中的吃内存大户。

地址空间中的各个条带相应于不同的内存段(memory segment),如:堆、栈之类的。记住。这些段仅仅是简单的内存地址范围,与Intel处理器的段没有关系。

1.1 32位经典内存布局

图 3

32位经典内存布局,程序起始1GB地址为内核空间,接下来是向下增长的栈空间和由0×40000000向上增长的mmap地址。而堆地址是从底部開始,去除ELF、代码段、数据段、常量段之后的地址并向上增长。

可是这样的布局有几个问题,首先是easy遭受溢出攻击。其次是,堆地址空间仅仅有不到1G有木有?假设mmap内存比較少地址非常浪费有木有?所以后来就有了还有一种内存布局

1.2 32位默认内存布局

图 4

当计算机开心、安全、可爱、正常的运转时。差点儿每个进程的各个段的起始虚拟地址都与图4全然一致,这也给远程发掘程序安全漏洞打开了方便之门。一个发掘过程往往须要引用绝对内存地址:栈地址。库函数地址等。远程攻击者必须依赖地址空间布局的一致性,摸索着选择这些地址。假设让他们猜个正着,有人就会被整了。因此,地址空间的随机排布方式逐渐流行起来。

Linux通过对栈、内存映射段、堆的起始地址加上随机的偏移量来打乱布局。不幸的是。32位地址空间相当紧凑,给随机化所留下的空当不大,削弱了这样的技巧的效果。

进程地址空间中最顶部的段是栈。大多数编程语言将之用于存储局部变量和函数參数。

调用一个方法或函数会将一个新的栈桢(stack frame)压入栈中。栈桢在函数返回时被清理。或许是由于数据严格的遵从LIFO的顺序,这个简单的设计意味着不必使用复杂的数据结构来追踪栈的内容,仅仅须要一个简单的指针指向栈的顶端就可以。

因此压栈(pushing)和退栈(popping)过程很迅速、准确。另外,持续的重用栈空间有助于使活跃的栈内存保持在CPU缓存中,从而加速訪问。进程中的每个线程都有属于自己的栈。

通过不断向栈中压入的数据,超出其容量就有会耗尽栈所相应的内存区域。这将触发一个页故障(page fault)。并被Linux的expand_stack()处理,它会调用acct_stack_growth()来检查是否还有合适的地方用于栈的增长。假设栈的大小低于RLIMIT_STACK(一般是8MB)。那么普通情况下栈会被加长。程序继续愉快的执行,感觉不到发生了什么事情。这是一种将栈扩展至所需大小的常规机制。然而,假设达到了最大的栈空间大小,就会栈溢出(stack overflow),程序收到一个段错误(Segmentation Fault)。当映射了的栈区域扩展到所需的大小后。它就不会再收缩回去,即使栈不那么满了。这就好比联邦预算,它总是在增长的。

动态栈增长是唯一一种訪问未映射内存区域(图中白色区域)而被同意的情形。

其他不论什么对未映射内存区域的訪问都会触发页故障,从而导致段错误。一些被映射的区域是仅仅读的,因此企图写这些区域也会导致段错误。

内存映射段

在栈的下方。是我们的内存映射段。此处,内核将文件的内容直接映射到内存。不论什么应用程序都能够通过Linux的mmap()系统调用(实现)或Windows的CreateFileMapping() / MapViewOfFile()请求这样的映射。内存映射是一种方便高效的文件I/O方式。所以它被用于载入动态库。创建一个不正确应于不论什么文件的匿名内存映射也是可能的。此方法用于存放程序的数据。在Linux中。假设你通过malloc()请求一大块内存,C执行库将会创建这样一个匿名映射而不是使用堆内存。

‘大块’意味着比MMAP_THRESHOLD还大,缺省是128KB,能够通过mallopt()调整。

说到堆,它是接下来的一块地址空间。

与栈一样。堆用于执行时内存分配。但不同点是,堆用于存储那些生存期与函数调用无关的数据。

大部分语言都提供了堆管理功能。因此,满足内存请求就成了语言执行时库及内核共同的任务。在C语言中,堆分配的接口是malloc()系列函数,而在具有垃圾收集功能的语言(如C#)中。此接口是newkeyword。

假设堆中有足够的空间来满足内存请求,它就能够被语言执行时库处理而不须要内核參与。否则,堆会被扩大,通过brk()系统调用(实现)来分配请求所需的内存块。堆管理是非常复杂的。须要精细的算法。应付我们程序中杂乱的分配模式,优化速度和内存使用效率。

处理一个堆请求所需的时间会大幅度的变动。实时系统通过特殊目的分配器来解决问题。堆也可能会变得零零碎碎,例如以下图所看到的:

图 5

BSS 数据段 代码段

最后。我们来看看最底部的内存段:BSS,数据段,代码段。在C语言中,BSS和数据段保存的都是静态(全局)变量的内容。差别在于BSS保存的是未被初始化的静态变量内容,它们的值不是直接在程序的源码中设定的。BSS内存区域是匿名的:它不映射到不论什么文件。

假设你写static int cntActiveUsers。则cntActiveUsers的内容就会保存在BSS中。

还有一方面。数据段保存在源码中已经初始化了的静态变量内容。这个内存区域不是匿名的。

它映射了一部分的程序二进制镜像,也就是源码中指定了初始值的静态变量。所以。假设你写static int cntWorkerBees = 10,则cntWorkerBees的内容就保存在数据段中了,并且初始值为10。虽然数据段映射了一个文件,但它是一个私有内存映射,这意味着更改此处的内存不会影响到被映射的文件。也必须如此。否则给全局变量赋值将会修改你硬盘上的二进制镜像,这是不可想象的。

下图中数据段的样例更加复杂,由于它用了一个指针。在此情况下,指针gonzo(4字节内存地址)本身的值保存在数据段中。而它所指向的实际字符串则不在这里。这个字符串保存在代码段中。代码段是仅仅读的,保存了你所有的代码外加零零碎碎的东西,比方字符串字面值。代码段将你的二进制文件也映射到了内存中。但对此区域的写操作都会使你的程序收到段错误。这有助于防范指针错误,尽管不像在C语言编程时就注意防范来得那么有效。下图展示了这些段以及我们样例中的变量:

图 6

你能够通过阅读文件/proc/pid_of_process/maps来检验一个Linux进程中的内存区域。记住一个段可能包括很多区域。

比方,每一个内存映射文件在mmap段中都有属于自己的区域,动态库拥有类似BSS和数据段的额外区域。

下一篇文章讲说明这些“区域”(area)的真正含义。有时人们提到“数据段”,指的就是所有的数据段+ BSS + 堆。

2 64位虚拟内存布局

64位系统的寻址空间比較大,所以仍然沿用了32位的经典布局,可是加上了随机的mmap起始地址,以防止溢出攻击。反正一时半会是用不了这么大的内存地址了。所以至少N多年不会变了。

首先, 眼下大部分的操作系统和应用程序并不须要16EB( 264 )如此巨大的地址空间, 实现64位长的地址仅仅会添加系统的复杂度和地址转换的成本, 带不来不论什么优点. 所以眼下的x86-64架构CPU都遵循AMD的Canonical form, 即仅仅有虚拟地址的最低48位才会在地址转换时被使用, 且不论什么虚拟地址的48位至63位必须与47位一致(sign extension). 也就是说, 总的虚拟地址空间为256TB( 248 ).


图 7

然后, 在这256TB的虚拟内存空间中, 0000000000000000 - 00007fffffffffff(128TB)为用户空间, ffff800000000000 - ffffffffffffffff(128TB)为内核空间. 这里须要注意的是, 内核空间中有非常多空洞, 越过第一个空洞后, ffff880000000000 - ffffc7ffffffffff(64TB)才是直接映射物理内存的区域, 也就是说默认的PAGE_OFFSET为ffff880000000000. 从这里我们也能够看出, 这么大的直接映射区域足够映射全部的物理内存, 所以眼下x86-64它不会在高内存架构存在, 那是,ZONE_HIGHMEM这个地区(参考部分).

版权声明:本文博客原创文章,博客,未经同意,不得转载。

转载于:https://www.cnblogs.com/gcczhongduan/p/4655112.html

内存管理--分发您的程序存储器相关推荐

  1. 深入理解STM32内存管理

    参考:详解ROM和RAM 作者:嵌入式实验楼 网址:https://mp.weixin.qq.com/s/y2aG7kX-6CTyeMzEJW_YHw 内存相关博文: 1.内存四区(代码区 静态区 栈 ...

  2. 内存管理单元(MMU)介绍

    MMU是存储器管理单元的缩写,是用来管理虚拟内存系统的器件.MMU通常是CPU的一部分,本身有少量存储空间存放从虚拟地址到物理地址的匹配表.此表称作TLB(转换旁置缓冲区).所有数据请求都送往MMU, ...

  3. 操作系统 —— (内存)内存管理

    文章目录 内存管理 内存管理主要有四个方面的功能: 内存管理技术 简单存储管理 段式存储管理 页式存储管理 功能2:虚拟页空间 实现:页表 快表TLB:提高访问速度 分页和分段有什么区别(内存管理)? ...

  4. 内存管理内幕--Jonathan Bartlett (johnnyb@eskimo.com), 技术总监, New Media Worx--

    Jonathan Bartlett (johnnyb@eskimo.com), 技术总监, New Media Worx 2004 年 11 月 29 日 本文将对 Linux™ 程序员可以使用的内存 ...

  5. ARM内存管理(MMU)详解

    嵌入式系统中,存储系统差别很大,可包含多种类型的存储器件,如 FLASH , SRAM , SDRAM , ROM 等,这些不同类型的存储器件速度和宽度等各不相同:在访问存储单元时,可能采取平板式的地 ...

  6. Objective-C内存管理知识总结

    原帖地址  http://www.cocoachina.com/bbs/read.php?tid-12760.html Objective-C的内存管理机制是比较灵活的,即可以拿来像C/C++一样用, ...

  7. 操作系统原理第八章:内存管理

    目录 1 内存管理背景 2 固定分区分配 3 动态内存分配 3.1 首先适应 (First-fit) 3.2 最佳适应 (Best-fit) 3.3 外碎片问题 4 分页 5 分页硬件支持 6 分段管 ...

  8. iOS内存管理策略和实践

    来源:http://www.baidu.com/link?url=irojqCBbZKsY7b0L2EBPkuEkfJ9MQvUf8kuNWQUXkBLk5b22Jl5rjozKaJS3n78jCnS ...

  9. php的内存划分,解析PHP中的内存管理,PHP动态分配和释放内存

    摘要 内存管理对于长期运行的程序,例如服务器守护程序,是相当重要的影响:因此,理解PHP是如何分配与释放内存的对于创建这类程序极为重要.本文将重点探讨PHP的内存管理问题. 一. 内存 在PHP中,填 ...

  10. iPhone/Mac Objective-C内存管理教程和原理剖析

    版权声明 此文版权归作者Vince Yuan (vince.yuan#gmail.com)所有.欢迎非营利性转载,转载时必须包含原始链接http://vinceyuan.cnblogs.com/,且必 ...

最新文章

  1. 宝安区2021年高考成绩查询入口,宝安区2021年初一学位网上预申请系统http:bajjk.sz.edu.cn/visitbagbcyjz...
  2. php access ole相片,[求助]怎样读取ACCESS数据库中的OLE对象的图片啊???
  3. 消息系统kafka原理解析
  4. python作者 es6_ES6 全套教程 ECMAScript6 (原著:阮一峰)(1)
  5. MySQL监控系统Lepus的搭建
  6. java setrotation_如何使用Java库将文档转换为横向模式?
  7. LeetCode 452. 用最少数量的箭打破气球(贪心)
  8. html5 微格式,HTML5 微格式和相关的属性名称
  9. php lpop 返回null,数据库读取数据返回 null 怎么办?
  10. 基于检索的自然语言处理模型研究梳理
  11. 怎样远程访问 MySQL
  12. LOJ #10130 点的距离
  13. 微服务学习之Gateway服务网关【Hoxton.SR1版】
  14. CocosCreator物理引擎Demo源码分析(1)-infinite-world
  15. pip下载镜像源汇总
  16. pygame.mask原理及使用pygame.mask实现精准碰撞检测
  17. 网线连接问题--部分短路
  18. Android usb广播 ACTION_USB_DEVICE_ATTACHED流程源码分析
  19. 品优购商城项目常见BUG解析
  20. MATLAB语言的串口助手

热门文章

  1. EMNLP 2022 和 COLING 2022,投哪个会议比较好?
  2. ACL2021奇葩标题大赏
  3. 【内推】AI独角兽-数美科技-NLP/CV/ASR等开放百余岗位,薪资诱人
  4. 深度学习1-tensorflow2.0自定义操作与建模方式
  5. 【理论篇】是时候彻底弄懂BERT模型了(建议收藏)
  6. 《MySQL技术内幕(SQL编程)》——数据类型
  7. 你还在因为数学对AI望而却步?看看这本秘籍吧
  8. 回顾2020年那些“领域第一本”,每一本都强烈推荐!
  9. 阿里免费开放一切AI算力的背后是什么?
  10. 驱动开发专家解读《寒江独钓——Windows内核安全编程》