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

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

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

智能推荐

云时代如何实现企业IT智能诊断?|对话阿里云MVP蒋烁淼(下) ..._weixin_33953249的博客-程序员宅基地

阿里云MVP、驻云科技CEO蒋烁淼4月11日做客《MVP时间》,为大家分析在云时代对于企业IT智能诊断的实践与探索。本篇为下期,上期文档直戳4、 云时代企业IT智能诊断传统情况下,客户通过监控的方式来发现系统问题、解决问题。在云计算的大背景下,传统监控慢慢力不从心。表现在: 监控对象范围有限:比较适合本地硬件与服务监控,不太适合对云...

Shiro源码分析----认证流程_镜水灵动的博客-程序员宅基地

由于本文是基于源码分析Shiro认证流程,所以假设阅读者对Shiro已经有一定的了解,如果对Shiro还不大了解的话,推荐一下博文:跟我学Shiro目录贴Apache Shiro作为一个优秀的权限框架,其最重要的两项工作:其一是认证,即解决登录的用户的身份是否合法;其二是用户登录后有什么样的权限。本文将基于Shiro源码来剖析Shiro的认证流程,只有深层次的理解Shiro认证流程,认证过程中各个...

木棒切割问题(***二分法)_满树的博客-程序员宅基地_木棒切割问题

木棒切割问题 给出N根木棒,长度均已知,现在希望通过切割它们来得到至少K段长度相等的木棒(长度必须是整数),问这些长度的木棒最长能有多长。 例如对三根长度分别为10,24,15 的木棒来说,假设 K = 7,即需要至少7段长度相等的木棒,那么可以得到的最大长度为6,在这种情况下,第一根木棒可以提供10/6 = 1段、第二根木棒可以提供24/6 = 4段、第三根木棒可以提供15/...

关于工作_qqshenyunzcz的博客-程序员宅基地

一、关于工作与生活      我有个有趣的观察,外企公司多的是25-35岁的白领,40岁以上的员工很少,二三十岁的外企员工是意气风发的,但外企公司40岁附近的经理人是很尴尬的。我见过的40岁附近的外企经理人大多在一直跳槽,最后大多跳到民企,比方说,唐骏。外企员工的成功很大程度上是公司的成功,并非个人的成功,西门子的确比国美大,但并不代表西门子中国经理比国美的老板强,甚至可以说差得很远。而进外企的人

3D目标检测——代码理解——OpenPCDet:验证eval部分分析_FridayFreedom++的博客-程序员宅基地

import io as sysioimport numbaimport numpy as npfrom .rotate_iou import [email protected] get_thresholds(scores: np.ndarray, num_gt, num_sample_pts=41): scores.sort() # 将得分的一维数组 升序排列,如[1,2,3,4] scores = scores[::

中国古典音乐_congsikuai0611的博客-程序员宅基地

中国古典音乐链接:http://www.guqu.net/ ...

随便推点

Nacos在linux环境下部署_凉拌~玛卡巴卡的博客-程序员宅基地_linux部署nacos

首先 Nacos 在linux环境下部署前提是linux环境下有安装过jdk8版本及以上,并且jdk环境变量配置没有问题。因为Nacos 是阿里巴巴基于springboot工程创建的一个项目,需要依赖jdk环境。linux下手动安装jdk及配置可以参考:https://blog.csdn.net/qq_44316726/article/details/116034329?spm=1001.2014.3001.55011、下载nacos的二进制压缩包;下载地址:https://github.com/a

Spring Boot security集成Keycloak_脱离动物猿的博客-程序员宅基地

集成Spring Securitypom.xml引入security<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId></dependency>application.yml中security-constraints可以删除application.yml

Windows无法为计算机分级,win7旗舰版系统检测评分时点击“为此计算机分级”无效怎么办..._普通网友的博客-程序员宅基地

我们在给win7旗舰版系统检测评分时,点击“为此计算机分级”按了多次都显示无效。这是什么原因呢?其实问题是由于C盘的盘符系统格式不是“NTFS”格式引起的。那么这个问题要怎么解决呢?下面一起看看具体操作步骤吧。具体方法如下:1、首先鼠标双击桌面“计算机”图标打开它,在计算机中查看本地磁盘(C:)是不是“NTFS”格式分区,选择本地磁盘(C:)点击鼠标右键,在弹出的菜单选项中选择“属性”;2、在弹出...

十进制转为十六进制_-BearWolf的博客-程序员宅基地

问题描述  十六进制数是在程序设计时经常要使用到的一种整数的表示方式。它有0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共16个符号,分别表示十进制数的0至15。十六进制的计数方法是满16进1,所以十进制数16在十六进制中是10,而十进制的17在十六进制中是11,以此类推,十进制的30在十六进制中是1E。  给出一个非负整数,将它表示成十六进制的形式。输入格式

数据结构与算法---栈_循梦的博客-程序员宅基地

栈基本概念栈是一种逻辑结构,是特殊的线性表。特殊在:只能在固定的一端操作只要满足上述条件,那么这种特殊的线性表就会呈现一种“后进先出”的逻辑,这种逻辑就被称为栈。由于约定了只能在线性表固定的一端进行操作,于是给栈这种特殊的线性表的插入删除,起个特殊的名称:栈顶(top of stack):可以进行插入删除的一端栈底:栈顶的对立端入栈:将节点插入栈顶之上,也称为压栈,函数名通常为push()出栈:将节点从栈顶剔除,也称为弹栈,函数名通常为pop()取栈顶:取得栈顶元素,但不出栈,函数

IF...ELSE...THEN分支结构_学习使我快乐……的博客-程序员宅基地

- 疑问? 如果计价单位为RMB,点击人民币按钮,RMB单位结果不变 如果计价单位为USD,点击美元按钮,USD单位结果不变- 分析? IF....THEN 如果....那么 ELSE 否则 .... END IF 结束- 解决方法Option Explicit'将人民币价格转换为美元价格Sub TESTPRICE() Dim PRICE, V 'V循环变量 PRICE = Cells(5, 2) '汇率 '循

推荐文章

热门文章

相关标签