两个不同的进程 虚拟地址相同_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 C获取键盘信息_linux/input.h 键盘编号-程序员宅基地

文章浏览阅读5.4k次,点赞4次,收藏13次。#include <stdio.h>#include <unistd.h>#include <termios.h> static struct termios initial_settings, new_settings;static int peek_character = -1;void init_keyboard(void);void clo..._linux/input.h 键盘编号

SaltStack数据系统_comment: no top file or master_tops data matches f-程序员宅基地

文章浏览阅读69次。文章目录1SaltStack数据系统2 SaltStack数据系统组件2.1 SaltStack组件之Grains2.2 SaltStack组件之Pillar2.3 Grains与Pillar的区别1SaltStack数据系统SaltStack有两大数据系统,分别是GrainsPillar2 SaltStack数据系统组件2.1 SaltStack组件之GrainsGrains是SaltStack的一个组件,其存放着minion启动时收集到的信息。Grains是SaltStack组件中非_comment: no top file or master_tops data matches found. please see master lo

error C2668: “swap”: 对重载函数的调用不明确_swap对重载函数的调用不明确-程序员宅基地

文章浏览阅读3.4k次,点赞6次,收藏3次。当出现这个错误提示的时候,很有可能代码并没有问题,而是编译器的设定问题。测试代码如下:#include using namespace std;//函数模板templatevoid swap(T &a,T &b){ T temp; temp = a; a = b; b = temp;}int main(int ,char **){ int a = 1, b _swap对重载函数的调用不明确

ZYNQ PCIe EP实现DMA+Linux交互,非常简洁的程序_c++ 往pcie发送数据-程序员宅基地

文章浏览阅读1w次,点赞8次,收藏120次。ZYNQ PCIe-DMA源码 例程 PS-PL交互 linux/裸机 verilog C/C++ZYNQ PCIe-DMA的实现过程一、概述二、基础知识三、系统总框架四、工作原理与工作模式五、接口时序六、资源使用情况七、PS-PL交互以及测试程序ZYNQ PCIe-DMA的实现过程近期在网上淘来个源码,看了之后觉得还不错。完全刷新我对ZYNQ的认知啊,原来ZYNQ也可以这么玩的。PS-PL交..._c++ 往pcie发送数据

Python-Django毕业设计员工宿舍管理系统(程序+Lw)_用python设计一个宿舍管理系统,要求能实现寝室信息的增加、删除、修改、查询以及-程序员宅基地

文章浏览阅读173次。该项目含有源码、文档、程序数据库、配套开发软件、软件安装教程项目运行环境配置:Pychram社区版py项目技术:django + python+ Vue 等等组成,B/S模式 +pychram管理等等。环境需要1.运行环境:最好是python3.7.7,我们在这个版本上开发的。其他版本理论上也可以。2.pycharm环境:pycharm都可以。推荐pycharm社区版;3.mysql环境:建议是用5.7版本均可。_用python设计一个宿舍管理系统,要求能实现寝室信息的增加、删除、修改、查询以及

linux使用apache搭建http服务器(文件服务器)_linux怎么搭http apache服务器-程序员宅基地

文章浏览阅读8.4k次,点赞5次,收藏41次。一、安装Apache$ sudo apt-get install apache2二、修改服务器访问端口Apache2的默认访问端口为80,可修改为其他端口(当端口被占用时需要更改其访问端口)进入apache2的安装目录 /etc/apache2/,修改ports.conf文件$ cd /etc/apache2/$ sudo chmod 775 ports.conf$ vim po..._linux怎么搭http apache服务器

随便推点

深入了解,html,head,body,document(文档)、视口、window的关系_body、html、视口三合一-程序员宅基地

文章浏览阅读579次。从DOM(文本对象模型来看)DOM将文档中的节点看作是一个个的对象,包括文档节点(document),元素节点(标签名),属性节点(不是元素节点的子节点)、文本节点,注释节点,上面谈到的每个节点都是一个对象,其中元素节点包括但不限于html、head、body,浏览器为我们创建了访问文档中的节点的入口,也就是document对象,其中document对象也是window对象的属性,document对象是包括html对象的我们所说的网页,一般由三种组成HTML(结构)、CSS(表现)、Js(形式,实现交_body、html、视口三合一

巴比特 | 元宇宙每日必读:传Meta计划将其VR头显Quest推向中国市场,正与腾讯进行洽谈,腾讯方回应称不予置评...-程序员宅基地

文章浏览阅读149次。摘要:据《科创板日报》7 月 4 日报道,有消息称,Meta 将重返中国,已经与多家中国科技公司进行了讨论,目前可能会和腾讯进行合作,后者或成为 Meta Quest 系列头显的独家经销商,且将为 Quest 头显开发 VR 游戏。对此,腾讯回应表示,不予置评。图片来源:由无界AI生成热点资讯腾讯将发布面向大模型训练的自研向量数据库据《科创板日报》7 月 4 日报道,腾讯云将在今日下午正式发布自研...

shell实例手册-程序员宅基地

文章浏览阅读151次。0 说明{ 手册制作: 雪松 更新日期: 2015-05-13 欢迎系统运维加入Q群: 198173206 # 加群请回答问题 欢迎运维开发加入Q群: 365534424 # 不定期技术分享 请使用"notepad++"或其它编辑器打开此文档, "alt+0"将函数折叠后方便查阅 请勿删除信息, 转载请说明出处, 抵制不道德行..._gawk '{ sum += $2 }; end { print sum }' /

NotImplementedError: Could not run ‘torchvision::nms‘ with arguments from the ‘CUDA‘ backend. This c_could not run torchvision::nms-程序员宅基地

文章浏览阅读610次。https://stackoverflow.com/questions/75103127/getting-notimplementederror-could-not-run-torchvisionnms-with-arguments-fr_could not run torchvision::nms

HTC硬件介绍_htc是什么硬件-程序员宅基地

文章浏览阅读399次。其中最重要的是头盔中两个屏幕,用的是比较高端的三星AMOLED屏幕,屏幕尺寸对角线为91.8mm,PPI(每英寸集成的像素)达到了447(像素密度越高表现出来的画面就更细腻)。体验者可以在一个小范围的空间中行走,体验制作好的内容。是通过摄像头不停的采集周围环境的图像来达到设备的姿态估计(比如噪音等一些没用的信息也会影响到它的准确性)。是通过计算机视觉,以及设备自身自带的传感器比如陀螺仪、加速器来实现位置的追踪。不需要外部硬件来定位。由LED阵列和横向纵向的两个马达,马达以非常高的频率扫描场景中的定位。_htc是什么硬件

基于 Python 深度学习的车辆特征分析系统,附源码_pycharm实时检测车辆及源码-程序员宅基地

文章浏览阅读1.7k次,点赞25次,收藏29次。而在机动车的自动识别过程中,通过利用深度学习的算法来让计算机通过不断地获取信息要素形成信息库,可以更好的提升计算机对于车辆的识别能力。本次就是通过利用了深度学习技术结合Python开发工具来设计一款能够在线通过图片分析来识别车辆的品牌的软件。_pycharm实时检测车辆及源码

推荐文章

热门文章

相关标签