【Linux】进程(7):地址空间

大家好,我是苏貝,本篇博客带大家了解Linux进程(7):地址空间,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️
在这里插入图片描述


目录

  • (A) 直接看代码,看现象
  • (B)基本理解
  • (C)细节
    • 1. 如何理解地址空间
      • a.什么是划分区域
    • 2. 为什么要有地址空间
      • a.将无序变成有序,让进程以统一的视角看待物理内存以及自己运行的各个区域
      • b.进程管理模块和内存管理模块进行解耦
      • c.拦截非法请求
    • 3. 进一步理解页表
    • 4. 进一步理解写时拷贝

(A) 直接看代码,看现象

修改.c文件
在这里插入图片描述

运行进程
在这里插入图片描述

先看黄色框,这个我们能理解,因为之前说过父子进程的数据,如果任意一个都不对数据写入,那么数据就是共享的,所以它们指向同一块数据空间,所以地址相同

再看红色框,我们也能理解。因为进程具有独立性,所以子进程对数据的修改,父进程是看不到的,所以它们打印同一个全局变量,但值不同

再看蓝色框,这就不能理解了,同一个地址的值怎么可能既是100也是300?所以这个地址绝对不可能是物理地址,是虚拟地址。引出下一个概念:虚拟地址

(B)基本理解

当我们将程序加载进内存中时,OS在物理内存中一定要给这个程序开辟一块空间,来保存进程的代码和数据。OS要创建进程的task_struct。我们之前只说task_struct能指向内存中的代码和数据,事实远比我们想的复杂
在这里插入图片描述

在OS内部还要创建地址空间(每个进程都有独立的地址空间)。地址空间在32位机器和64位机器上的大小是不同的。我们以32位机器为例(下面讲的都是在32位机器下),地址空间从低到高一共有4GB的空间。我们之前用C语言打印的地址都是地址空间范围内所对应的地址,而非物理地址

进程的PCB会指向地址空间。

进程的代码和数据都在物理内存里面,进程想访问数据时,数据并不在地址空间上保存,地址空间会给我们提供线性的连续的地址(即虚拟地址),让我们未来提供虚拟地址找到物理地址

在这里插入图片描述

如何通过虚拟地址找到物理地址呢?
在计算机体系结构中还存在页表(每个进程都有自己独立的页表)。页表主要负责将地址空间的虚拟地址和对应的物理地址之间建立映射关系。只要建立好了映射关系,未来上层使用虚拟地址访问时,OS会自动拿着虚拟地址查页表转换成物理地址,最后访问到数据

在这里插入图片描述

现在有进程中有全局变量g_val,&g_val得到的0x601054是虚拟地址,假如g_val的物理地址是0x11223344,那么在页表中就会存储这些地址
在这里插入图片描述

现在进程创建了一个子进程,OS也会为子进程创建task_struct、地址空间和页表(每个进程都有自己独立的地址空间和页表)。
子进程没有代码和数据,它会继承父进程的代码和很多属性,相当于父进程pcb里的很多属性就可以用来初始化子进程。所以子进程的task_struct除了pid,ppid等,大部分属性都和父进程的一样。
子进程的地址空间和页表都是直接拷贝父进程的,所以子进程的地址空间里也有g_val的虚拟地址0x601054,子进程的页表里也有g_val的物理地址
在这里插入图片描述

现在让子进程对数据进行写入:将g_val的值从100改为300。
由于进程具有独立性,所以子进程对g_val的修改,不能影响父进程,所以肯定不能在0x11223344对应的空间修改。OS在写入时,发现g_val不仅被子进程在使用,还同时被父进程使用,所以写入暂停,OS在物理内存中重新开辟一块空间,假设物理地址为0x22334455,然后将g_val的值100拷贝到新空间中。再用新的物理地址覆盖页表中老的物理地址,重新构建映射。
上面的工作(叫写时拷贝)做完,OS再继续执行写入操作。将新的空间的值改为300

在这里插入图片描述

至此,子进程修改g_val的值,只是修改了物理内存和页表,可是上层用到的虚拟地址依旧是0x601054,虽然虚拟地址相同,但被映射到物理内存的不同的区域,所以出现了我们在(A)直接看代码,看现象里地址一样,但值不同的情况

(C)细节

为什么要写时拷贝?
我们上面说了是为了保证进程的独立性。那为什么不在创建子进程的时候,就把数据全部给子进程拷贝?因为如果有数据是父子进程都不需要修改的话,那将这些数据也给子进程拷贝一份,这不就是在浪费空间吗?所以,写时拷贝的本质就是按需申请

1. 如何理解地址空间

a.什么是划分区域

在小学的时候,大家都应该和同桌在桌子上划过“三八线”吧,现在假设你和同桌2个人共用一个100cm的桌子, 你们每个人50cm,那这如何用计算机语言来描述呢?
在这里插入图片描述

只需要构建2个结构体,第二个结构体表示一个课桌分为左右两部分,第一个结构体表示每部分的开始和结束位置,再构建第二个结构体的结构体变量,最后将左右两块空间的起始和终止位置都赋值即可

如果同桌太过分了,每次都侵占了属于你的10cm区域,再用计算机语言来描述

在这里插入图片描述

事实上,地址空间本质是内核的一个struct结构体(struct mm_struct),内核的很多属性都是表示start和end的范围。如何证明呢?

让我们来查看Linux的源代码,我们看到有许多表示开始和结束的变量

在这里插入图片描述

2. 为什么要有地址空间

a.将无序变成有序,让进程以统一的视角看待物理内存以及自己运行的各个区域

如果没有地址空间,那么进程的task_struct就要能指向物理内存中对应的所有的数据和代码,这对进程来讲是比较困难的

在这里插入图片描述

现在有了地址空间和页表。实际的物理内存中,代码区、数据区、堆区……都是无序的,如果让进程的task_struct直接指向物理内存的对应的各种代码和数据区,那么可能从低地址往高地址,第一个是初始化数据区,第二个是堆区……就不像有了地址空间和页表,在进程的task_struct视角,从低地址往高地址一定是代码区、初始化数据区……
在这里插入图片描述

所以地址空间的第一个好处就是将无序变有序(对task_struct),让进程以统一的视角看待自己运行的各个区域

b.进程管理模块和内存管理模块进行解耦

比如现在进程要申请一段堆空间,那先在地址空间的堆区申请一段空间,但是进程不是立马就要用,所以暂时不在物理内存申请空间,也不在页表建立映射关系(只有虚拟地址,没有物理地址),等到进程需要用这段空间,再在物理内存申请空间并建立映射关系

换言之,如果要对进程做各种管理,那么内存管理都可以延迟处理,因此地址空间和页表的存在,能让进程管理模块和内存管理模块解耦

c.拦截非法请求

当我们写的代码在遍历时要访问地址空间的堆区(我们在上层使用的都是虚拟地址),但发生了越界,此时将这个越界的虚拟地址到页表中查,发现没有这个虚拟地址,证明没有对应的映射关系,所以OS就拦截了这次请求,不让它做任何操作,就不会有往物理内存中写入的操作,所以能拦截非法请求

3. 进一步理解页表

CPU内的寄存器(如CR3)能将当前页表的地址保存在CPU内
MMU(硬件):将虚拟地址结合页表转换成物理地址
在这里插入图片描述

页表中有许多标记位,比如用来确定当前物理地址指向的空间是否在内存中,是:标记位为1;否:标记位为0

什么情况下,当前物理地址指向的空间不在内存中呢?
进程挂起。如果操作系统内存特别吃紧,且进程处于阻塞态,那么操作系统会将内存中的代码和数据加载到磁盘的swap分区,那么此时物理地址指向的空间就不在内存中,该标记位就为0

页表中还有rwx权限标记位。我们以前见过下面的代码,你觉得这个代码能被VS运行通过吗?
在这里插入图片描述

显然不能,在语言层面上讲,因为”hello world”是常量字符串,位于字符常量区,所以不能被修改
在操作系统层面,就是字符常量区的虚拟地址在页表上的rwx权限标记位为r,没有w,所以在想将“web”写入时,系统检测到了错误,在转化成物理地址中将进程终止,所以根本没有写入物理内存

4. 进一步理解写时拷贝

在进程没有创建子进程时,全局变量g_val的虚拟地址被记录在页表中,对应的权限标记位为rw,可读可写

在这里插入图片描述

进程创建子进程后,全局变量g_val的虚拟地址被记录在页表中,对应的权限标记位被OS设为r。子进程会拷贝父进程的地址空间和页表,所以子进程的g_val在页表对应权限标记位也是r

在这里插入图片描述

当父子进程任意一个想对g_val进行写入时,将g_val的虚拟地址到页表中查,发现其权限标记位为r,OS识别到错误,开始判断

  1. 是不是数据不在物理内存(进程挂起了,页表中对应标记位为0):如果是,触发缺页中断(让OS重新在物理内存中开辟空间,重新建立映射,把标记位置为1,然后再继续访问)。这属于正常情况
  2. 是不是数据需要写时拷贝(OS如何知道需要写时拷贝,这个以后再讲),如果是,就发生写时拷贝
  3. 上面2种都不是,进行异常处理

好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️

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

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

相关文章

MATLAB基础应用精讲-【数模应用】二元Logit分析(最终篇)(附python、MATLAB和R语言代码实现)

目录 算法原理 SPSSAU 1、二元logistic分析思路说明 2、如何使用SPSSAU进行二元logistic操作 3、二元logistic相关问题 算法流程 一、分析前准备 1、确定分析项 2.多重共线性判断 3.数据预处理 二、回归基本情况分析 三、模型拟合评价 1、似然比检验 2、拟合优…

Linux - 深入理解/proc虚拟文件系统:从基础到高级

文章目录 Linux /proc虚拟文件系统/proc/self使用 /proc/self 的优势/proc/self 的使用案例案例1:获取当前进程的状态信息案例2:获取当前进程的命令行参数案例3:获取当前进程的内存映射案例4:获取当前进程的文件描述符 /proc中进程…

【GIS教程】土地利用转移矩阵

随着科技社会的不断进步,人类活动对地理环境的影响与塑造日益明显,土地不断的侵蚀与改变也导致一系列的环境问题日益突出。土地利用/覆盖(LUCC)作为全球环境变化研究的重点问题为越来越多的国际研究机构所重视,研究它的…

酷开系统丨酷开科技智慧AI 让家庭智能化近在眼前

科技改变生活,从3G-4G-5G,再到即将突破的6G;从传统有人驾驶的车辆到现在的无人驾驶车辆;从九十年代的大哥大“砖头”便携电话,到蓝绿屏按键手机、触摸屏手机,再到智能手机;从传统数字密码到现在…

信息系统项目管理师0146:输入(9项目范围管理—9.3规划范围管理—9.3.1输入)

点击查看专栏目录 文章目录 9.3 规划范围管理9.3.1 输入9.3 规划范围管理 规划范围管理是为了记录如何定义、确认和控制项目范围及产品范围,而创建范围管理计划的过程。本过程的主要作用是在整个项目期间对如何管理范围提供指南和方向。本过程仅开展一次或仅在项目的预定义点开…

【RuoYi】框架中使用wangdietor富文本编辑器

一、前言 在上篇博客中,介绍了RuoYi中如何实现文件的上传与下载,那么这篇博客讲一下如何在RuoYi中使用富文本编辑器,这部分的内容是向B站程序员青戈学习的,当然我这里就会把学到的内容做一个总结,当然也会说…

信息系统项目管理师0147:工具与技术(9项目范围管理—9.3规划范围管理—9.3.2工具与技术)

点击查看专栏目录 文章目录 9.3.2 工具与技术 9.3.2 工具与技术 专家判断 规划范围管理过程中,应征求具备如下领域相关专业知识或接受过相关培训的个人或小组 的意见,涉及的领域包括:以往类似项目;特定行业、学科和应用领域的信息…

服务器远程连接工具有哪些?

【天联】是一款功能强大的服务器远程连接工具,它可以让用户通过网络远程连接到目标服务器,实现远程操作和管理。【天联】的使用场景非常广泛,特别适用于以下几个领域: 零售、收银软件应用的远程管理:【天联】可以结合医…

Stable Diffusion【应用篇】【图片修复】:模糊头像照片的高清修复

本文主要是回复一下后台小伙伴留言的问题。经小伙伴本人同意后,允许使用待修复的照片。 我们先看一下待修复的照片。 在向我咨询之前,小伙伴也自己进行了尝试,如果直接使用Stable Diffusion的后期处理功能,出来的图片效果是这样的…

Spring Security3.0.1版本

前言: 抽象Spring Security3.0上一篇 在上一篇中,我们完成了对Security导入,快速入门,和对自动配置的简单验证 对登录流程的分析和Security基本原理 补充: 先解决上一篇留下的问题,端口和端点的区别 端…

Javascript系统学习(三)

前端模块化前端模块化CommonJS、AMD、CMD、ES6_commonjs amd cmd es6模块化-CSDN博客 ES6: <script type"module" src"main.js"></script> //默认导出 export default function(ctx) {... } ----------------------------------- //模块命名…

每日题库:Huawe数通HCIA——全部【813道】

1.关于ARP报文的说法错误的是?单选 A.ARP报文不能被转发到其他广播域 B.ARP应答报文是单播方发送的 C.任何链路层协议都需要ARP协议辅助获取数据链路层标识 DARP请求报文是广播发送的 答案:C  解析: STP协议不需要ARP辅助 2.园区网络搭建时,使用以下哪种协议可以避免出现二层…

[AIGC] 详解Mockito - 简单易学的Java单元测试框架

在Java的世界中, 单元测试是一项非常重要的任务. Mockito作为一个强大灵活的mock框架&#xff0c;可以帮助我们有效的编写和管理我们的单元测试. 了解并掌握Mockito的使用对于提高我们的开发效率和保证我们的软件质量有着巨大的帮助. 文章目录 什么是Mockito?Mockito的核心API…

UE4_环境_材质函数

学习笔记&#xff0c;不喜勿喷&#xff0c;欢迎指正&#xff0c;侵权立删&#xff01; 1、建立材质函数Distance_Fun&#xff0c;勾选公开到库。 2、添加函数输入节点FunctionInput&#xff0c; 这个输入我们想作为混合材质属性BlendMaterialAttributes的alpha输入节点&#x…

苍穹外卖笔记-06-菜品管理-菜品分类,公共字段填充

菜品分类 1 菜品分类模块1.1 需求分析与设计1.1.1 产品原型1.1.2 接口设计1.1.3 表设计 1.3 代码实现1.4 测试分类分页查询启用禁用分类修改分类信息新增菜品分类删除菜品分类 2 公共字段自动填充2.1 问题分析2.2 实现思路自定义注解AutoFill自定义切面AutoFillAspectMapper接口…

C++ | Leetcode C++题解之第136题只出现一次的数字

题目&#xff1a; 题解&#xff1a; class Solution { public:int singleNumber(vector<int>& nums) {int ret 0;for (auto e: nums) ret ^ e;return ret;} };

如何在手机上恢复误删除的视频?

说到移动设备上的视频恢复&#xff0c;我们仍将揭开4种解决方案供您使用。希望它们对您的案件有所帮助。 众所周知&#xff0c;我们移动设备上的视频应用程序将创建一个缓存文件夹&#xff0c;以在它们永远消失之前临时存储已删除的项目。因此&#xff0c;有许多iPhone / Andr…

《系统架构设计师教程(第2版)》第11章-未来信息综合技术-02-人工智能技术概述

文章目录 1. 人工智能&#xff08;AI&#xff09;1.1 弱人工智能1.2 强人工智能 2. 人工智能的发展历程3. 人工智能关键技术31. 自然语言处理 (Natural Language Processing)3.2 计算机视觉 (Computer Vision)3.3 知识图谱 (Knowledge Graph)3.4 人机交互 (Human-Computer Inte…

2. keepalived结合LVS配合使用

keepalived结合LVS配合使用 1、后端nfs存储提供项目文件2、后端nfs上集中安装MySQL&#xff0c;共用数据库3、业务服务器通过LNMP正常部署wordpress博客&#xff0c;客户端通过DNS解析可正常访问4、所有业务服务器上修改arp参数、配置VIP5、配置keepalived实现LVS高可用5.1 kee…

来自工业界的知识库 RAG 服务(三),FinGLM 竞赛获奖项目详解

背景介绍 前面介绍过工业界的 RAG 服务 QAnything 和 RagFlow 的详细设计&#xff0c;也介绍过来自学术界的 一些优化手段。 前一阵子刚好看到智谱组织的一个金融大模型比赛 FinGLM&#xff0c;主要做就是 RAG 服务的竞赛&#xff0c;深入研究了其中的几个获奖作品&#xff…