两个不同的进程 虚拟地址相同_Linux的进程地址空间[二] - VMA-程序员宅基地

技术标签: 两个不同的进程 虚拟地址相同  

f5a40ad8fef6af7e19048dbebbe55ebc.png

Linux的进程地址空间[一]

segments

一个进程通常由加载一个elf文件启动,而elf文件是由若干segments组成的,同样的,进程地址空间也由许多不同属性的segments组成,但这与硬件意义上的segmentation机制(参考这篇文章)不同,后者在某些体系结构(比如x86)中起重要作用,充当内存中物理地址连续的独立空间。Linux进程中的segment是虚拟地址空间中用于保存数据的区域,只在虚拟地址上连续。

97be58b5c1c1cf44607541a34b41cea2.png

text段包含了当前运行进程的二进制代码,其起始地址在IA32体系中中通常为0x08048000,在IA64体系中通常为0x0000000000400000(都是虚拟地址哈)。data段存储已初始化的全局变量,bss段存储未初始化的全局变量。从上图可以看出,这3个segments是紧挨者的,因为它们的大小是确定的,不会动态变化。

与之相对应的就是heap段和stack段。heap段存储动态分配的内存中的数据,stack段用于保存局部变量和实现函数/过程调用的上下文,它们的大小都是会在进程运行过程中发生变化的,因此中间留有空隙,heap向上增长,stack向下增长,因为不知道heap和stack哪个会用的多一些,这样设置可以最大限度的利用中间的空隙空间。

还有一个段比较特殊,是mmap()系统调用映射出来的。mmap映射的大小也是不确定的。3GB的虚拟地址空间已经很大了,但heap段, stack段,mmap段在动态增长的过程还是有重叠(碰撞)的可能。为了避免重叠发生,通常将mmap映射段的起始地址选在TASK_SIZE/3(也就是1GB)的位置。如果是64位系统,则虚拟地址空间更加巨大,几乎不可能发生重叠。

如果stack段和mmap段都采用固定的起始地址,这样实现起来简单,而且所有Linux系统都能保持统一,但是真实的世界不是那么简单纯洁的,正邪双方的较量一直存在。对于攻击者来说,如果他知道你的这些segments的起始地址,那么他构建恶意代码(比如通过缓冲区溢出获得栈内存区域的访问权,进而恶意操纵栈的内容)就变得容易了。

一个可以采用的反制措施就是不为这些segments的起点选择固定位置,而是在每次新进程启动时(通过设置PF_RANDOMIZE标志)随机改变这些值的设置。

a84a4a9f374be5df3e3618dfd17915cc.png

那这些segments的加载顺序是怎样的呢?以下图为例,首先通过execve()执行elf,则该可执行文件的text段,data段,stack段就建立了,在进程运行过程中,可能需要借助ld.so加载动态链接库,比如最常用的libc,则libc.so的text段,data段也建立了,而后可能通过mmap()的匿名映射来实现与其他进程的共享内存,还有可能通过brk()来扩大heap段的大小。

a27909885af19ad6708aac110e456443.png

vm_area_struct

在Linux中,每个segment用一个vm_area_struct(以下简称vma)结构体表示。vma是通过一个双向链表(早期的内核实现是单向链表)串起来的,现存的vma按起始地址以递增次序被归入链表中,每个vma是这个链表里的一个节点。

177a9236588150380c8c0d1433f27b1a.png

在用户空间可通过"/proc/PID/maps"接口来查看一个进程的所有vma在虚拟地址空间的分布情况,其内部实现靠的就是对这个链表的遍历。

38f6ee473ddf24233ce40eeeb6db7ad2.png

同时,vma又通过红黑树(red black tree)组织起来,每个vma又是这个红黑树里的一个节点。为什么要同时使用两种数据结构呢?使用链表管理固然简单方便,但是通过查找链表找到与特定地址关联的vma,其时间复杂度是O(N),而现实应用中,在进程地址空间中查找vma又是非常频繁的操作(比如发生page fault的时候)。

使用红黑树的话时间复杂度是O(

),尤其在vma数量很多的时候,可以显著减少查找所需的时间(数量翻倍,查找次数也仅多一次)。同时,红黑树是一种非平衡二叉树,可以简化重新平衡树的过程。

现在我们来看一下vm_area_struct结构体在Linux中是如何定义的(这里为了讲解的需要对结构体内元素的分布有所调整,事实上,结构体元素的分布是有讲究的,将相关的元素相邻放置并按cache line对齐,有利于它们在cache中处于同一条cache line上,提高效率):

struct vm_area_struct 
{
      
	unsigned long vm_start; 
	unsigned long vm_end;  
	struct vm_area_struct *vm_next, *vm_prev; 
	rb_node_t vm_rb; 
        unsigned long vm_flags;
        struct file * vm_file;
        unsigned long vm_pgoff;
	struct mm_struct * vm_mm; 
	...
}

其中,vm_start和vm_end分别是这个vma所指向区域的起始地址和结束地址,虽然vma是虚拟地址空间,但最终毕竟是要映射到物理内存上去的,所以也要求是4KB对齐的。

vm_next是指向链表的下一个vma,vm_rb是作为红黑树的一个节点。

a3bd3f372c46afae0b3d18ddc84190e7.png

vm_flags描述的是vma的属性,flag可以是VM_READ、VM_WRITE、VM_EXEC、VM_SHARED,分别指定vma的内容是否可以读、写、执行,或者由几个进程共享。前面介绍的页表PTE中也有类似的Read/Write权限限制位,那它和vma中的这些标志位是什么关系呢?

69483703f15ee76a6a526f7cc334f623.png

vma由许多的虚拟pages组成,每个虚拟page需要经过page table的转换才能找到对应的物理页面。PTE中的Read/Write位是由软件设置的,设置依据就是这个page所属的vma,因此一个vma设置的VM_READ/VM_WRITE属性会复制到这个vma所含pages的PTE中。

之后,硬件MMU就可以在地址翻译的过程中根据PTE的标志位来检测访问是否合法,这也是为什么PTE是一个软件实现的东西,但又必须按照处理器定义的格式去填充,这可以理解为软硬件之间的一种约定。那可以用软件去检测PTE么?当然可以,但肯定没有用专门的硬件单元来处理更快嘛。

可执行文件和动态链接库的text段和data段是基于elf文件的,mmap对文件的映射也是对应外部存储介质中这个被映射的文件的,这两种情况下,vm_file指向这个被映射的文件,进而可获得该文件的inode信息,而"vm_pgoff"是这个段在该文件内的偏移。

对于text段,一般偏移就是0。对于heap段,stack段以及mmap的匿名映射,没有与之相对应的文件实体,此时"vm_file"就为NULL,"vm_pgoff"的值没有意义。

那一个进程是怎么找到它的这些vma的呢?请看下文分解。

参考:

How The Kernel Manages Your Memory

原创文章,转载请注明出处。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39832628/article/details/110994300

智能推荐

Linux 机器间配置 SSH 免密登录_从linux服务器上ssh连接其他主机免输密码-程序员宅基地

文章浏览阅读1.4k次。在日常工作中,服务器常常会有多台。特别是应用服务器存在多台的情况下,在每台机器手动部署或升级服务,每次登录多台机器特别麻烦,通过一台机器跳转每次输入密码(一般都是超强密码)也麻烦。所以说配置机器间的免密,对日常工作来说可以简化操作流程,节省宝贵时间。这篇就简单说说如何配置多台机器间的免密功能。_从linux服务器上ssh连接其他主机免输密码

python预测值和真实值_机器学习中用什么图可以表示预测数据与真实数据的差异?...-程序员宅基地

文章浏览阅读2.5k次。但是实际上学习机器学习可能很困难。您要么使用行为类似于“黑匣子”的预构建包,要么在其中传递数据,另一端则产生魔力,或者您必须处理高级数学和线性代数。每种方法都使学习机器学习充满挑战和威胁。用Python搭建机器学习模型预测房租价格旨在向您介绍机器学习的基本概念。在继续学习时,您将从头开始构建第一个模型以进行预测,同时准确地了解模型的工作原理。(用Python搭建机器学习模型预测房租价格基于我们的机..._python机器学习预测数据比较作图

端口扫描--zmap-程序员宅基地

文章浏览阅读1k次。ZMap被设计用来针对整个IPv4地址空间或其中的大部分实施综合扫描的工具。ZMap是研究者手中的利器,但在运行ZMap时,请注意,您很有 可能正在以每秒140万个包的速度扫描整个IPv4地址空间 。我们建议用户即使在实施小范围扫描之前,也联系一下本地网络的管理员并参考我们列举的最佳扫描体验。默认情况下,ZMap会对于指定端口实施尽可能大速率的TCP SYN扫描。较为保守的情况下,对..._zmap输出结果带端口

uva1587BOX-程序员宅基地

文章浏览阅读114次。uva1587BOX 给定6个矩形的长和宽wi和hi(1≤wi,hi≤1000),判断它们能否构成长方体的6个面。思路是首先排序,每个矩形都是x<y,就是短边x,长边y,然后对六个矩形进行二级排序,排序以后构成长方体的条件有两步,第一步,首先是三对相同的长..._给定6个矩形的长和宽w和h(l≤w,h≤1000),判断它们能否构成长方

Etherent VLAN MPLS LDP Info-程序员宅基地

文章浏览阅读771次。以太网/VLAN/MPLSTopic:以太网1. 以太网帧格式以太网帧格式可分为Ethernet II和IEEE802.3,主要区别在于源MAC地址后俩字节的的长度,所幸的是,后者定义的有效长度值与前者定义的有效类型值无一相同,这样就容易区分两种帧格式了。一、前序字段(前导码/帧间隙:Preamble/SFD)(SFD:Start of Frame Delimiter)前 序字段..._报文eth和vlan以及mpls可以共存吗

华为v系列服务器,服务器的v码-程序员宅基地

文章浏览阅读599次。服务器的v码 内容精选换一换给指定的备份策略添加一个标签。URI格式POST /v2/{project_id}/backuppolicy/{policy_id}/tagsPOST /v2/{project_id}/backuppolicy/{policy_id}/tags参数说明参数是否必选描述project_id是项目IDpolicy_id是策略ID参数说明参数是根据给定的裸金属服务器ID列表,..._vjum

随便推点

Java解析XML_java 解析xml-程序员宅基地

文章浏览阅读1k次,点赞17次,收藏23次。XML现在已经成为一种通用的数据交换格式,平台的无关性使得很多场合都需要用到XML。本文将详细介绍用Java解析XML的四种方法在做一般的XML数据交换过程中,我更乐意传递XML字符串,而不是格式化的XML Document。这就涉及到XML字符串和Xml Document的转换问题,说白了这是个很简单的问题,本文就各种XML解析器分别列举如下,以方便自己今后查阅。=========..._java 解析xml

【AI视野·今日NLP 自然语言处理论文速览 第二十期】Thu, 8 Jul 2021_自然语言处理最新论文-程序员宅基地

文章浏览阅读301次。AI视野·今日CS.NLP 自然语言处理论文速览Thu, 8 Jul 2021Totally 25 papers????上期速览更多精彩请移步主页Daily Computation and Language PapersDORA: Toward Policy Optimization for Task-oriented Dialogue System with Efficient Context Authors Hyunmin Jeon, Gary Geunbae Lee最近,通过_自然语言处理最新论文

Delphi XE 取得当前时间戳的几个函数_delphi时间戳-程序员宅基地

文章浏览阅读501次,点赞11次,收藏9次。时间戳 delphi_delphi时间戳

bugfix之Parameter is not valid for operation xxx. Parameter is [req]. Processor is [body].-程序员宅基地

文章浏览阅读1k次。对比发现是没有加构造方法,加上注解@NoArgsConstructor 和。@AllArgsConstructor之后解决。_parameter is not valid for operation

Qt键盘事件:捕获和处理用户输入_qt 捕获键盘输入-程序员宅基地

文章浏览阅读397次。通过使用类似的方法,您可以根据自己的需求在Qt应用程序中捕获和处理键盘事件。键盘事件的处理为用户提供了更多的交互性和灵活性,使得Qt应用程序更加强大和易用。在main函数中,我们创建了一个QApplication对象和一个MyWidget对象,并显示了MyWidget窗口。函数会被调用,并传递一个QKeyEvent对象作为参数,该对象包含了有关键盘事件的详细信息,如按下的键码、修饰键状态等。在上面的示例中,我们创建了一个自定义的QWidget派生类MyWidget,并重写了它的。_qt 捕获键盘输入

TL437x-IDK开发板硬件说明书_tl437x nand-程序员宅基地

文章浏览阅读268次。Revision History DraftDate Revision No. Description 2018/2/27 V1.0 1.初始版本。 目 录前言 31处理器 42 FLASH 43 RAM 54 FRAM 5..._tl437x nand

推荐文章

热门文章

相关标签