浅析Linux进程地址空间

前言

现代处理器基本都支持虚拟内存管理,在开启虚存管理时,程序只能访问到虚拟地址,处理器的内存管理单元(MMU)会自动完成虚拟地址到物理地址的转换。基于虚拟内存机制,操作系统可以为每个运行中的进程创建独享的虚拟地址空间,在这个空间中执行的程序,无法感知系统中其它进程的存在,从而使得不同的进程在运行时可以互不干扰。

进程地址空间的大小

虚拟地址空间的最大长度与系统中实际可用的物理内存数量无关,而是取决于硬件平台支持的寻址空间大小,即处理器的位数。32位处理器平台下,支持的虚拟地址空间范围为0x00000000~0xFFFFFFFF,总大小为2^32 字节,即4GB;而在64位处理器平台上,虚拟地址空间的范围从0x0000000000000000扩展到了0xFFFFFFFFFFFFFFFF,总大小为2^64 字节。用户进程通常无法直接访问全部地址空间,操作系统会将一部分地址空间划分给内核程序,具体的划分策略依赖于操作系统的实现。

进程地址空间的布局

下图是在典型的32位和64位Linux操作系统上,运行时进程的地址空间布局:
在这里插入图片描述

基于内核的管理策略,进程虚拟地址空间并没有全部分配给进程使用。Linux将进程地址空间划分成两个部分:位于高地址部分的内核地址空间和位于低地址部分的用户地址空间,其中

  • 内核地址空间:内核总是驻留在内存中,是操作系统的一部分。内核空间专为内核保留,并且对于系统中所有的进程都是相同的。内核空间只允许具备高特权级的内核程序进行访问;对于用户程序,只能通过系统调用等方式陷入内核空间中以访问系统提供的资源;
  • 用户地址空间:进程只能访问用户地址空间。用户地址空间保存了用户程序的运行指令和数据。内核在创建进程时,会依据用户可执行文件中提供的信息在用户空间中创建必要的区域,并为用户进程维护环境变量、堆和栈等信息。对于系统中的每个进程,其用户地址空间是彼此分离,完全隔绝的,进程只能访问属于自己的用户地址空间部分的数据

用户地址空间区域

由上图可以看出,无论是32位系统或是64位系统,进程用户地址空间除了地址空间大小不同外,内存布局基本相同,通常都包含以下几个部分:

  • 当前运行程序的二进制代码,对应于代码段;
  • 存储只读数据和可读写数据的段,如常量和全局变量;
  • 用于动态分配内存的堆;
  • 存储局部变量以及实现过程调用的栈;
  • 保存命令行参数和环境变量的区域。

内存映射区域

图中有一个特殊的区域没有画出,就是内存映射区域。内存映射区域通常位于堆和栈之间,用于将磁盘中的内容直接映射到内存中进行访问。Linux系统中的程序可以通过mmap系统调用来请求这种功能,相较于直接读写磁盘文件,内存映射提供了一种更加高效的文件IO方式,典型的应用场景就是动态库的装载。

进程地址空间访问

尽管系统中每个进程都拥有巨大的虚拟地址空间,实际可使用的物理内存确是有限的,因此内核必须考虑如何合理地安排有限的物理地址到虚拟地址空间区域的映射。Linux内核为每个进程维护了独立的进程页表,并管理着系统中所有的物理内存,通过动态建立虚拟地址和物理地址的页表映射,每个进程只会访问所需要的那一部分物理内存,从而实现了内存的高效使用。下图简要显示了进程虚拟地址空间中的地址到实际物理地址的转换过程:
在这里插入图片描述

缺页异常

内核遵循按需分配的原则,在进程实际需要某个虚拟内存区域的数据之前,内核不会为其建立虚拟内存到物理内存的页面映射。若进程访问的虚拟地址空间部分没有与具体的物理页帧建立关联,处理器会自动触发缺页异常,并调用内核设置的缺页异常处理函数进行处理。内核缺页异常处理函数会检测触发缺页异常的虚拟地址合法性,并在通过后,为其分配物理页帧和建立页面映射关系,并返回重新执行触发异常的指令。

非法内存访问

完整的进程地址空间被划分成了不同的区域,对于不同的区域,其设置的访问权限也都不相同,这同时也就意味着,用户程序在随意访问了某个内存地址时,如内核空间部分的部分,则可能触发不可恢复的错误。典型的几种访问了非法地址的情况如下所示:

  • 内核空间区域:内核空间区域对应的页表项,设置了高特权级访问权限,对于运行在低特权级的用户程序来说,是没有资格访问的;
  • 只读权限区域:只读权限的区域包含代码段、只读数据段以及其它被设置了只读权限的区域,如果对这类区域进行写操作,则会触发异常;
  • 极低地址区域:大部分操作系统中,都不允许进程访问极小的内存地址,对应于地址空间中保留未用的部分区域。也正因如此,C语言中NULL宏默认被定义成0,访问NULL指针则会触发空指针异常;
  • 未分配的区域:堆和栈之间的区域默认情况下,内核没有分配给进程使用。若用户在没有申请该段区域的情况下进行访问,会导致错误。

相关参考

  • 《深入理解Linux内核架构》
  • 《程序员的自我修养—链接、装载与库》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/318874.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DHCP中继【新华三】

理论【DHCP服务器可以对其直连的网段中的pc,分配其IP地址等服务,但是,对于跨网段进行分配IP地址,需要中间有DHCP中继进行传达,由DHCP中继指定DHCP服务器的位置,可以很好的对其跨网段分配IP地址起到指引的作…

如何激活数据要素价值

文章目录 前言一、数据作为生产要素的背景二、数据作为新型生产要素,是价值创造的重要源泉(一)生产要素是经济活动中的基本要素(二)激活数据要素价值,要从理论上认识数据要素的基本特征(三&…

爬虫—中信证券资管产品抓取

爬虫—中信证券资管产品抓取 中信证券资管产品板块网址:http://www.cs.ecitic.com/newsite/cpzx/jrcpxxgs/zgcp/ 页面截图如下: 目标:抓取上图中红框内的所有资产信息 按F12进入开发者工具模式,在Elements板块下,在…

大数据StarRocks(七):数据表创建

1. 基本概念 1.1 Row & Column 一张表包括行(Row)和列(Column)。Row 即用户的一行数据。Column 用于描述一行数据中不同的字段。 ⚫ 在默认的数据模型中,Column 只分为排序列和非排序列。存储引擎会按照排序列对…

Flask 小程序菜品搜索

mina/pages/food/index.wxml <!--index.wxml--> <!--1px 750/320 2.34rpx;--> <view class"container"><!--轮播图--><view class"swiper-container"><swiper class"swiper_box" autoplay"{{autoplay}…

中仕公考:2024年上半年中小学教师资格考试(笔试)报名已开始

2024年上半年中小学教师资格考试(笔试)报名工作于1月12日开始&#xff0c;此次笔试在31个省(自治区、直辖市)举办&#xff0c;各省(自治区、直辖市)的报名公告将陆续上网。 个别地区报名截止时间有所差异&#xff0c;上海1月13日报名截止&#xff0c;浙江、天津、河南1月14日截…

Grounding DINO:开放集目标检测,将基于Transformer的检测器DINO与真值预训练相结合

文章目录 背景知识补充CLIP (Contrastive Language-Image Pre-training)&#xff1a;打破文字和图像之间的壁垒DINO(Data-INterpolating Neural Network)&#xff1a;视觉 Transformer 的自监督学习Stable Diffusion&#xff1a;从文本描述中生成详细的图像Open-set Detector开…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《与新能源互补和独立参加多级市场的抽蓄电站容量分配策略》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 这个标题涉及到抽蓄电站在能源系统中的角色&#xff0c;特别是在多级市场中的参与&#xff0c;并强调了新能源的互补性以及抽蓄电站的独立性。下面我将…

java swing UI第三方设计器JFormDesiner和FlatLaf UI

安装JFormDesiner 官网&#xff1a;https://www.formdev.com/ 先去IDEA的插件市场安装吧 JFormDesiner是非开源&#xff0c;且付费的插件&#xff0c;可以自己去找找不付费的使用方法。在swing可视化设计UI非常高效快捷&#xff0c;初学者可能需要一定时间探索&#xff0c;熟…

最左前缀法则

概念 最左前缀法则是针对于复合索引而言的&#xff0c;也就是说一个索引有多个字段那么索引的查询从最左列开始&#xff0c;并且不跳过索引的列&#xff0c;如果跳过索引中的某一列&#xff0c;那么&#xff0c;会导致索引部分失效(跳过列之后的索引失效)如果出现了范围查询(&…

学习redis有效期和数据类型

1、安装redis和连接redis 参考&#xff1a;ubuntu安装单个redis服务_ubuntu redis单机版安装-CSDN博客 连接redis&#xff1a;redis-cli.exe -h localhost -p 6379 -a 123456 2、Redis数据类型 以下操作我们在图形化界面演示。 2.1、五种常用数据类型介绍 Redis存储的是key…

数据结构与算法教程,数据结构C语言版教程!(第三部分、栈(Stack)和队列(Queue)详解)六

第三部分、栈(Stack)和队列(Queue)详解 栈和队列&#xff0c;严格意义上来说&#xff0c;也属于线性表&#xff0c;因为它们也都用于存储逻辑关系为 "一对一" 的数据&#xff0c;但由于它们比较特殊&#xff0c;因此将其单独作为一章&#xff0c;做重点讲解。 使用栈…

UISegmentedControl控件定制

1.在xib中设计如下: 背景颜色: 段标题与数量 : 2.在代码中控制 关联控件 注册控件事件 控件事件处理函数实现: 定制Title颜色 4 --- > UIControlStateSelected 0 --- > UIControlStateNormal 最终实现效果: 取控件选中时的索引与显示文本: 输出:

我在代码随想录|写代码Day7之454.四数相加II ,​ 383. 赎金信​,​ 15. 三数之和​

454.四数相加II 题目 解题思路 四个数字相加的和为0,我们要选俩数组,让他们的笛卡尔积储存在哈希表中,然后我们要找的是这俩数和的相反数,然后就是将后面俩数组相加在后面的数组和中找相反数. 383. 赎金信 解题思路 题目意思是让在字符串1中找到字母组成字符串2所以找字符串1…

Sentinel微服务保护

文章目录 Sentinel微服务保护1.初识Sentinel1.1.雪崩问题及解决方案1.1.1.雪崩问题1.1.2.解决方案1.1.3.总结 1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel1.3.2.安装Sentinel 1.4.微服务整合Sentinel 2.流量控制2.1.簇点链路2.1.快速入门2.2.流控模式2.2.1.…

【C++】wxWidgets库实现窗体程序

一、安装wxWidgets库 在Debian系统上使用wxWidgets库来创建一个基本的窗体程序&#xff0c;首先需要确保已经安装了wxWidgets相关的库和开发工具。下面是安装wxWidgets的步骤&#xff1a; 打开终端&#xff0c;使用下述命令安装wxWidgets库及其开发文件&#xff1a; sudo ap…

Tomcat解压打包文件和并部署

一、文件压缩和上传解压 1.本地打包好dist.tar.gz文件 2.通过xftp拖拽上传到知道文件夹下,或者通过命令: cp dist.tar.gz /path/to/destination/folder注:将dist.tar.gz复制到 /path/to/destination/folder文件夹下,该文件夹只是举个例子怎么复制和解压! 3.进入/path/…

ENNOID-BMS从控板分析-基于LTC6813的版本

LTC6813简单说明 单体电压采集部分&#xff0c;总共可以采集18个电芯电压&#xff0c;这18个电压分别交给3个16位Delta-Sigma ADC来进行采样&#xff1b;官方手册宣称的采样误差低于2.2mV&#xff0c;采样范围为0~5V&#xff0c;所有18个电芯采样一次只要290uS时间。电压均衡部…

Python中的列表跟C/C++里面的数组什么关系?

你好&#xff0c;我是安然无虞。 文章目录 Python数据类型列表创建列表新增列表元素append方法insert方法 删除列表元素pop方法remove方法 查找列表元素in相关index方法 下标访问列表元素负索引 遍历列表元素子列表提取拼接列表 相关extend方法 列表常用接口汇总列表操作列表的…

SpringCloud Aliba-Nacos-从入门到学废【1】

&#x1f95a;今日鸡汤&#x1f95a; 当你最倒霉地时候一定要扛住。 因为&#xff0c;那正是你运气该上升的时候。 ——《一人之下》 目录 &#x1f9c8;1.Nacos介绍 &#x1f9c2;2.Nacos服务提供者注册 &#x1f953;3.Nacos服务消费者 &#x1f32d;4.Nacos作为配置中心…