【Linux】进程地址空间

目录

引入

进程地址空间

虚拟地址与物理地址

如何理解虚拟地址的不同区域

写时拷贝

动态开辟的细节

为什么存在进程地址空间

避免地址被随意访问

进程管理和内存管理解耦合

使进程用统一的视角看待代码和数据


引入

🎃我们写一个这样的程序,运行并观察其输出结果。

#include <iostream>
#include <unistd.h>
#include <cstdio>
#include <cerrno>
#include <cstring>

using namespace std;

int main()
{
    int value = 10;   //定义一个变量
    pid_t id = fork();
    if (id == 0)   //子进程
    {
        while(1)
        {
            value++;    //改变value的值
            printf("我是子进程,我的pid是: %d,value是: %d,&value是: %p\n",getpid(),value,&value); //输出变量值
            sleep(1);
        }
    }
    else if (id > 0)  //父进程
    {
        while(1)
        {
            printf("我是父进程,我的pid是: %d,value是: %d,&value是: %p\n",getpid(),value,&value);  //输出变量值
            sleep(1);
        }
    }
    else  //fork出错
    {
        cout << errno << ": " << strerror(errno) << endl;
    }
    return 0;
}

 

🎃可以观察到,父子进程都有一个 value 值,且共用一个地址。而子进程改变 value 时父进程的 value 却不受影响

🎃假设,我们使用的这个地址就是物理地址的话,可能会出现读取同一个地址而出现两个不同的值的情况吗?

🎃因此我们得出一个结论: 在语言层面用的地址并非物理地址,而是虚拟地址

🎃我们在用C/C++语言所看到的地址,全部都是虚拟地址!而用户一概看不到物理地址,而是由OS统一管理

🎃我们使用的这个虚拟地址总的叫进程地址空间又叫 mm_struct ,是一种线性的结构,其通过页表的某种映射关系,从而找到物理内存。

进程地址空间

讲个故事吧:有个大富翁,他有很多的私生子。每个私生子不知道彼此的存在,因此都觉得大富翁的所有财产本质上也是自己的。因此,需要用钱的之后,只要找大富翁要就可以了,但也不能一下子要太多,否则大富翁会拒绝这种无礼的请求。而大富翁为了避免出现忘记给儿子们画的饼的尴尬情况,因此需要将他曾经画过的饼都管理起来。

🎃对号入座之后我们便能够发现,大富翁就是OS,私生子就是一个个进程。而其画的饼其实就是进程地址空间,本质上就是一个内核数据结构,struct mm_struct 。

虚拟地址与物理地址

如何理解虚拟地址的不同区域

🎃由于mm_struct本质上是一个线性结构,因此只要对线性区域进行指定 start 和 end 即可完成区域的划分,因此 mm_struct 内都是一段一段区域的划分,区域之间就叫做虚拟地址线性地址。将来只需要修改区域边界的位置便可以修改区域的大小。

🎃之后 mm_struct 便可以借助页表与MMU(内存管理单元)与物理内存确立映射关系、建立联系

🎃不仅如此,页表之中还存储了对于该空间的权限,正如一个常量区之中的字符串,我们可以对其读取却无法更改其内容。便是因为在页表之中,我们对该空间只有读权限而没有写权限。因此无法进行写入。

写时拷贝

🎃这时我们就可以回过头来讲讲,如何做到用一个地址却能得到两个值?

🎃在父进程创建子进程之前,申请了一个变量 value,因此在进程地址空间中存在一个地址,能够通过映射找到物理内存中的 value

🎃之后父进程创建了子进程,子进程会继承父进程的进程地址空间,因此二者存储 value 的虚拟地址是相同的,并映射到同一块物理内存。若子进程未进行写入,则两个进程便会保持原有的映射关系

🎃若子进程对值进行修改,便会触发写时拷贝,在物理内存的新地址中拷贝一份新的值进行修改,之后修改页表的映射,指向这块区域

🎃值得注意的是,哪个进程先进行修改,哪个进程就触发写时拷贝

动态开辟的细节

🎃不知道是否想过一个问题,动态开辟的空间是一申请就给我们呢?还是使用的时候再给?

🎃在动态开辟在申请时到使用前有个空窗期,这段时间内空间就被闲置了,而 OS 一般不允许任何的浪费和不高效的操作

🎃因此动态开辟时值分配虚拟内存,当要使用该空间时再分配物理内存,完善页表之中的映射关系。

为什么存在进程地址空间

避免地址被随意访问

🎃若直接使用物理内存,则在访问空间时无法检测野指针问题,放任指针随意地修改,可能会使数据受损或导致其他进程崩溃出错

进程管理和内存管理解耦合

🎃如此使用进程地址空间后,管理进程时并不关心内存是如何管理的

🎃同理,管理内存是也不关心进程是如何管理的,实现了进程管理和内存管理的解耦合再使用页表将二者关联起来

使进程用统一的视角看待代码和数据

🎃原代码被编译的时候就是按照虚拟地址空间的方式,对代码和数据完成了对应的编制

🎃这是由于虚拟地址这样的策略并不只影响 OS,编译器也要遵守。

🎃因此在内存中打开文件时,自然就有了对应的物理地址,之后在运行的时候若对函数进行调用,通过映射就会找到函数的虚拟地址(当前物理地址中存的是虚拟地址),再通过映射便可以找到函数体(再通过映射找到存函数体的物理地址)。

🎃因此 cpu 中读取的都是虚拟地址。 ---这样便实现使进程用统一的视角看待代码和数据

🎃且进程的代码和数据并非一直都在内存中,而是用多少加载多少不再使用就将其从内存之中移除


🎃好了,今天进程地址空间的讲解到这里就结束了,如果这篇文章对你有用的话还请留下你的三连加关注

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

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

相关文章

算法记录 | Day50 动态规划

123.买卖股票的最佳时机III 思路&#xff1a; 1.确定dp数组以及下标的含义 最多可完成两笔交易意味着总共有三种情况&#xff1a;买卖一次&#xff0c;买卖两次&#xff0c;不买卖。 具体到每一天结束总共有 5 种状态&#xff1a; 未进行买卖状态&#xff1b;第一次买入状…

springboot - spring.factories

spring.factories 是什么&#xff1f; spring.factories 是 Spring Boot 自动配置的核心机制之一&#xff0c;它用于自动注册 Spring Boot 中的各种自动配置类&#xff0c;从而实现自动化配置的目的。在 Spring Boot 应用程序启动时&#xff0c;Spring Boot 会自动扫描 classp…

深度解读:《数字孪生世界白皮书(2023)》全方位剖析

2023年初&#xff0c;中国信息通信研究院发布了《数字孪生城市产业图谱研究报告&#xff08;2022&#xff09;》&#xff0c;报告中提出我国数字孪生产业四阶段体系&#xff0c;2020年到2030年是我国数字孪生产业增长期&#xff0c;当前数字孪生市场需求和技术均处于高速发展阶…

5月跳槽有风险,不跳也有?

今天讲讲跳槽。 说实话跳槽是为了寻求更好的发展&#xff0c;但在跳槽前我们也不能确定下家就是更好的归宿&#xff0c;这就更加需要我们审慎地去对待&#xff0c;不能盲目跳槽。 其次&#xff0c;我们离职和跳槽&#xff0c;其中的原因很大一部分是目前薪资不符合预期。 那…

C. Permutation Game(博弈 + 拓扑的思想)

Problem - C - Codeforces 经过漫长的一天&#xff0c; Aice和Bob决定玩一个小游戏。游戏棋盘由n个格子组成&#xff0c;在一条直线上&#xff0c;编号从1到n,每个格子包含一个数字4;,qy在1到n.之间&#xff0c;而且没有两个格子包含相同的数字。 一个棋子被放在其中一个格子里…

什么牌子蓝牙耳机好用不贵?国产性价比高的蓝牙耳机推荐

相较于有线耳机&#xff0c;无线蓝牙耳机更便携、功能更丰富&#xff0c;不用受到耳机孔与线的限制。那么&#xff0c;什么牌子的蓝牙耳机好用不贵&#xff1f;针对这个问题&#xff0c;我给大家推荐几款国产性价比高的蓝牙耳机&#xff0c;可以当个参考。 一、南卡小音舱Lite…

Spring使用注解存储和读取对象

文章目录 一、存储Bean对象配置扫描添加注解存储Bean对象注解使用范围Bean的命名五大类注解的关系为什么需要五大类注解? 二、方法注解BeanBean重命名 三、对象注入属性注入Setter注入构造方法注入Autowired 和 Resource 的区别 一、存储Bean对象 之前我们存储Bean时&#xff…

5 Redis缓存穿透、击穿、雪崩、分布式锁、布隆过滤器

1 Redis 应用问题解决 1.1 缓存穿透 1.1.1 问题描述 key 对应的数据在数据源并不存在&#xff0c;每次针对此 key 的请求从缓存获取不到&#xff0c;请求都会压到数据源&#xff08;数据库&#xff09;&#xff0c;从而可能压垮数据源。比如 用一个不存在的用户 id 获取用户…

一份标准的软件测试方案模板

第一章 概述 ​ 软件的错误是不可避免的&#xff0c;所以必须经过严格的测试。通过对本软件的测试&#xff0c;尽可能的发现软件中的错误&#xff0c;借以减少系统内部各模块的逻辑&#xff0c;功能上的缺陷和错误&#xff0c;保证每个单元能正确地实现其预期的功能。检测和排…

亚马逊云科技开启您的云财务管理之旅:云财务运营

亚马逊云科技“开启您的云财务管理之旅”系列内容提出了关于如何启动和实施一个成功的云财务管理CFM战略的建议。云财务管理CFM的三个原则&#xff1a;SEE-查看、SAVE-节省和PLAN-计划。接下来介绍的是第四个阶段&#xff1a;RUN-运营。 在这一阶段&#xff0c;可以了解云财务管…

vue 做一个文本展示 点击文本弹出element ui的时间选择器 但不会出现element ui时间组件的那个输入框

我们先来创建一个vue2项目 引入element ui 然后 找到一个组件 这样写 <template><div><el-date-pickerv-model"value"type"datetimerange"align"right"unlink-panelsrange-separator"至"start-placeholder"开始日…

C/C++的命名空间和调用函数的详细讲解

目录 空函数 调用函数 调用 执行流程 命名空间 在创建函数时&#xff0c;必须编写其定义。所有函数定义包括以下组成部分&#xff1a; 名称&#xff1a;每个函数都必须有一个名称。通常&#xff0c;适用于变量名称的规则同样也适用于函数名称。形参列表&#xff1a;调用函…

手机摄影笔记(二)

第5章 镜头语言 镜头语言分类&#xff08;8个&#xff09;&#xff1a; 推&#xff1a;从远到近 拉&#xff1a;从近到远 摇&#xff1a;机位固定&#xff0c;旋转手机拍全景或者跟着拍摄对象进行摇摄&#xff08;跟摇&#xff09;.通常用此方式来介绍环境时&#xff0c;表现的…

开放原子训练营(第三季)inBuilder低代码开发实验室---报销单录入系统

作为一名低代码初学者&#xff0c;我使用inBuilder系统设计了一款报销单录入系统&#xff0c;实现了报销单录入与显示报销单列表的功能&#xff08;如图1与图2所示&#xff09;&#xff0c;并获得了很多开发心得。从inBuilder系统的优点、缺点以及开发过程三方面出发&#xff0…

基于SpringBoot,vue的家政服务平台的设计与实现

背景 以往的家政服务管理平台的管理&#xff0c;一般都是纸质文件来管理家政服务信息&#xff0c;传统的管理方式已经无法满足现代人们的需求&#xff1b;使用家政服务管理平台, 首先可以大幅提高家政服务信息检索&#xff0c;只需输入家政服务相关信息就能在数秒内反馈想要的…

JavaScript学习(一)

一、JavaScript的背景及知识结构 1、三个问题 什么是JavaScript&#xff1f;JavaScript能干什么&#xff1f;JavaScript是由什么构成的&#xff1f;怎样学习JavaScript&#xff1f; 2、什么是JavaScript&#xff1f; ①JavaScript是一种轻量级的编程语言&#xff1b;借鉴了J…

【SSA-LSTM】基于麻雀算法优化LSTM 模型预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

C#_Struct与Class的差异

简述 struct属于值类型&#xff0c;class属于引用类型 存储地址 struct储存于栈&#xff0c;class储存于堆&#xff08;class于栈中储存引用&#xff09; 传参性质 struct属于值传递&#xff0c;在函数内对参数进行修改&#xff0c;不会修改struct class处于引用传递&…

行为型模式-状态模式

状态模式 概述 【例】通过按钮来控制一个电梯的状态&#xff0c;一个电梯有开门状态&#xff0c;关门状态&#xff0c;停止状态&#xff0c;运行状态。每一种状态改变&#xff0c;都有可能要根据其他状态来更新处理。例如&#xff0c;如果电梯门现在处于运行时状态&#xff0…

MySQL

关系型数据库 数据结构&#xff1a;二维表格 库 -> 表 -> 列&#xff08;字段&#xff09;&#xff1a;用来描述对象的一个属性 -> 行&#xff08;记录&#xff09;&#xff1a;用来描述一个对象的信息 市面上&#xff1a;MySQL 、Mariadb 、PostgreSQL 、 Oracle&a…