作家
登录

剖析内存中的程序之秘,快来看吧!

作者: 来源: 2018-01-19 11:34:21 阅读 我要评论

年前最后一场技巧盛宴 | 1月27日与京东、日记易技巧大年夜咖畅聊智能化运维成长趋势!


ELF Binary Image Mapped Into Memory

Kernel/User Memory Split

分析内存中的法度榜样之秘

Kernel/User Memory Split

内存治理是操作体系的核心义务;它对法度榜样员和体系治理员来说也是至关重要的。在接下来的几篇文┞仿中,我将大年夜实践出发着眼于内存治理,并深刻到它的内部构造。固然这些概念很通用,但示例大年夜都来自于 32 位 x86 架构的 Linux 和 Windows 上。这第一篇文┞仿描述了在内存中法度榜样若何分布。

在一个多义务操作体系中的每个过程都运行在它本身的内存“沙箱”中。这个沙箱是一个虚拟地址空间virtual address space,在 32 位的模式中它总共有 4GB 的内存地址块。这些虚拟地址是经由过程内核页表page table映射到物理地址的,并且这些虚拟地址是由操作体系内菏攀来保护,进而被过程所花费的。每个过程都有它本身的一组页表,然则这里有点玄机。一旦虚拟地址被启用,这些虚拟地址将被应用到这台电脑上的 所有软件包含内核本身。是以,一部分虚拟地址空间必须保存给内核应用:

Process Switch Effects style=Process Switch Effects style="text-align: center;">Flexible Process Address Space Layout In Linux

然则,这并不是说内核就应用了很多的物理内存,恰好相反,它只应用了很少一部分可用的地址空间映射到其所须要的物理内存。内核空间在内核页表中被标记为独有应用于 特权代码 (ring 2 或更低),是以,如不雅一个用户模式的法度榜样测验测验去拜访它,将触发一个页面故障缺点。在 Linux 中,内核空间是始终存在的,并且在所有过程中都映射雷同的物理内存。内核代码和数据老是可寻址的,预备随时去处理中断或者体系调用。比拟之下,用户模式中的地址空间,在每次过程切换时都邑产生变更:

Flexible Process Address Space Layout In Linux

当计算机照样快活、安然的时代时,在机械中的几乎每个过程上,那些段的肇端虚拟地址都是完全雷同的。这将使长途发掘安然马脚变得轻易。马脚应用经常须要去引用绝对内存地位:比如在栈中的一个地址,一个库函数的地址,等等。长途进击可以闭着眼睛选择这个地址,因为地址空间都是雷同的。当进击者们如许做的时刻,人们就会受到伤害。是以,地址空间随机化开端风行起来。Linux 会经由过程在其肇端地址上增长偏移量来随机化栈、内存映射段、以及堆。不幸的是,32 位的地址空间是异常拥挤的,为地址空间随机化留下的空间不多,是以 妨碍了地址空间随机化的效不雅。

在过程地址空间中最高的段是栈,在大年夜多半编程说话中它存储本地变量和函数参数。调用一个办法或者函数将推送一个新的栈帧stack frame到这个栈。当函数返回时这个栈帧被删除。这个简单的设计,可能是因为数据严格遵守 落后先出(LIFO) 的次序,这意味着跟踪栈内容时不须要复杂的数据构造 —— 一个指向栈顶的简单指针就可以做到。推入和弹出也是以而异常快且精确。也可能是,持续的┞坊区重用往往会在 CPU 缓存 中保持活泼的┞坊内存,如许可以加快拜访速度。过程中的每个线程都有它本身的┞坊。

向栈中推送更多的而不是刚合适的数据可能会耗尽栈的映射区域。这将触发一个页面故障,在 Linux 中它是经由过程 expand_stack() 来处理的,它会去调用 acct_stack_growth() 来检查栈的增长是否正常。如不雅栈的大年夜小低于 RLIMIT_STACK 的值(一般是 8MB 大年夜小),那么这是一个正常的┞坊增长和法度榜样的合理应用,不然可能是产生了未知问题。这是一个栈大年夜小按需调节的常见机制。然则,栈的大年夜小达到了上述限制,将会产生一个栈溢出,并且,法度榜样将会收到一个段故障Segmentation Fault缺点。当映射的┞坊区为知足须要而扩大后,在栈缩小时,映射区域并不会紧缩。就像美国联邦当局的预算一样,它只会扩大。

动态栈增长是 独一例外的情况 ,当它去拜访一个未竽暌钩射的内存区域,如上图中白色部分,是许可的。除此之外的任何其它拜访未竽暌钩射的内存区域将触发一个页面故障,导致段故障。一些映射区域是只读的,是以,测验测验去写入到这些区域也将触发一个段故障。

在栈的下面,有内存映射段。在这里,内核将文件内容直接映射到内存。任何应用法度榜样都可以经由过程 Linux 的 mmap() 体系调用( 代码实现)或者 Windows 的 CreateFileMapping() / MapViewOfFile() 来请求一个映射。内存映射是实现文件 I/O 的便利高效的方法。是以,它经常被用于加载动态库。有时刻,也被用于去创建一个并不匹配任何文件的匿名内存映射,这种映射经常被用做法度榜样数据的替代。在 Linux 中,如不雅你经由过程 


  推荐阅读

  斯坦福的AI算法能预测死亡!这对临终关怀来说或许是件好事......

年前最后一场技巧盛宴 | 1月27日与京东、日记易技巧大年夜咖畅聊智能化运维成长趋势!应用人工智能技巧来猜测病人什么时刻会去世, 这听起来就像是反乌托邦科幻剧《黑镜》里才有的情节。>>>详细阅读


本文标题:剖析内存中的程序之秘,快来看吧!

地址:http://www.17bianji.com/lsqh/40381.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)