虚拟地址空间

news2024/11/17 6:03:07

本节目录

  • 1.如何理解区域划分
  • 2.为什么一个变量可以存储两个不同的值?
  • 3.深入理解虚拟地址空间
    • 为什么要有地址空间?
  • 4.理解什么是挂起?

1.虚拟地址空间究竟是什么?
2.映射关系的维护是谁做的?

1.如何理解区域划分

所谓的区域划分,本质是在一个范围里定义start和end。

struct destop
{
	int start;
	int end;
};

struct destop one = { 1, 50 };
struct destop two = { 51, 100 };

虚拟地址空间是一种内核数据结构,它里面至少要有对各个区域的划分。

struct addr_room
{
	int code_start;
	int code_end;
	
	int init_start;
	int init_end;

	int uninit_start;
	int uninit_end;

	int heap_start;
	int heap_end;

	int stack_start;
	int stack_end; 

	//... 其他的属性
};

地址空间和页表(用户级)是每个进程都私有一份。(页表是一种数据结构,它内部有映射关系,也有权限的管理,+MMU)
只要保证每一个进程的页表映射的是物理内存的不同区域,就能做到进程之间不会互相干扰,进而保证进程的独立性。

2.为什么一个变量可以存储两个不同的值?

首先我们观察下面一段代码:

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 
  5 int g_val = 0;
  6 int main()
  7 {
  8   pid_t id = fork();
  9   if(id <0)
 10   {
 11     perror("fork");
 12     return 0;
 13   }
 14   else if(id == 0)
 15   {
 16     printf("child[%d]:%d,%p\n",getpid(),g_val,&g_val);
 17   }
 18   else
 19   {
 20     printf("parent[%d]:%d,%p\n",getpid(),g_val,&g_val);                                                                                                                                                      
 21   }
 22   return 0;
 23 }

运行结果:

[jyf@VM-12-14-centos lesson9]$ ./a.out
parent[4479]:0,0x601050
child[4480]:0,0x601050

我们发现变量值和变量地址是一模一样的,很好理解呀,因为子进程是以父进程为模板,父进程并没有对变量值做任何修改。
我们在将代码进行修改:

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 
  5 int g_val = 0;
  6 int main()
  7 {
  8   pid_t id = fork();
  9   if(id <0)
 10   {
 11     perror("fork");
 12     return 0;
 13   }
 14   else if(id == 0)
 15   { //子进程肯定先跑完,也就是子进程先修改,完成之后,父进程在读取
 16     g_val = 100;
 17     printf("child[%d]:%d,%p\n",getpid(),g_val,&g_val);
 18   }
 19   else //parent 
 20   {
 21     sleep(3);
 22     printf("parent[%d]:%d,%p\n",getpid(),g_val,&g_val);
 23   }
 24   sleep(1);                                                                                                                                                                                                  
 25   return 0;                                                                                                                                                                        
 26 }              

运行结果:

[jyf@VM-12-14-centos lesson9]$ ./a.out
child[6691]:100,0x601058
parent[6690]:0,0x601058

我们发现父子进程,输出的变量地址是一样的,但变量的值不同。

一个变量可以存储两个不同的值吗?答案是否定的。输出的变量值不同说明它们绝对不是同一个变量,但输出的地址相同,说明它们不是物理地址,在Linux环境下,它叫做虚拟地址,我们在C/C++下,看到的都是虚拟地址,物理地址用户一概看不到,由OS统一管理,将虚拟地址映射成物理地址。进程地址空间是一种内核的数据结构,每一个进程都私有一份进程地址空间和页表,只要保证进程虚拟地址通过页表映射的是物理内存的不同区域,就能做到进程之间不会互相干扰,保证进程的独立性。所以父子进程的g_val的虚拟地址是一样的,当子进程修改g_val的值,通过页表映射到物理内存的不同区域,就出现了类似一个变量内存储两个不同的值的现象。
如此pid_t id = fork(); 中的id值为什么可以有两个返回值相信大家都能理解了。

在这里插入图片描述

3.深入理解虚拟地址空间

一些Linux指令:readelf -s 可执行文件, 用于查看可执行程序中的符号表。
objdump -f 可执行文件,用于查看可执行程序中文件头相关信息,一个反汇编工具。

[jyf@VM-12-14-centos lesson9]$ objdump -f a.out

a.out:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0000000000400560


当我们的程序通过编译形成可执行程序的时候,,还没有加载到内存的时候,请问我们程序的内部有地址吗?
可执行程序在编译的时候,内部其实就已经有地址了。
地址空间不要仅仅理解为OS要遵守的,编译器也要遵守。即编译器在编译代码的时候,就已经给我们形成了各个区域,代码区,数据区等等,并且,采用Linux一样的编制方式,给每一个变量,每一个代码都进行了编址,故,程序在编译的时候,每一个字段早已经具有了一个虚拟地址!!!
程序内部的地址,依旧用的是编译器编译好的虚拟地址,当程序加载到内存的时候,每行代码,每个变量便具有了一个外部的物理地址。
所以CPU读取到指令的时候,指令内部的地址是虚拟地址。可见,每一个变量,每一个函数都有地址,编译器给的,同样它们也一定被加载到物理内存中。

在这里插入图片描述

为什么要有地址空间?

1.凡是非法访问或者映射,OS都会识别到,并终止这个进程。这样可以做到有效保护内存。
我们知道地址空间和页表都是OS创建并维护的,是不是就意味着凡是使用地址空间和页表进行映射,也一定要在OS的监管之下进行访问,也便保护了物理内存中的所有合法数据,包括各个进程,以及内核的相关有效数据。

2.因为有地址空间和页表的存在,是不是我们的物理内存可以对未来的数据进行任意位置的加载?
当然可以。
这样物理内存的分配和进程的管理就可以做到没有关系,这样内存管理模块和进程管理模块就完成了解耦合。
从这我们可知,空间配置器配置的地址是虚拟地址,我们在C/C++中new/malloc申请空间的时候,本质是在虚拟地址空间进行申请。

如果我申请了物理空间,但我不立马使用,是不是空间的浪费呢?是的。
本质上,因为地址空间的存在,所以上层申请空间,其实是在地址空间上进行申请,物理内存甚至一个字节都不给你!!!而当你真正进行物理地址空间的访问的时候,才执行内存的相关管理算法,帮你申请内存,构建页表映射关系(是由OS自动帮你完成的,用户包括进程完全0感知),然后在让你进行内存的访问。这种延迟分配的策略,来提高整机的效率,几乎内存的有效使用是100%的。这也就是**缺页中断技术。**也就是说,你申请空间,系统已经给你分配了虚拟地址空间,但还没有给你分配物理地址,这种技术叫做缺页中断技术。

3.因为在物理内存上,理论可以任意位置加载,所以物理内存中几乎所有数据和代码都是乱序的。
但是,因为页表的存在,它可以将页表中的虚拟地址和物理地址进行映射,那么可见在进程的视角下,所有的内存分布,都可以是有序的。
地址空间加页表的存在可以将内存分布有序化。
地址空间是操作系统给进程画的大饼。进程要访问物理内存中的数据和代码,可能此时并不在物理内存中。同样的也可以让不同的进程映射不同的物理内存区域,是不是很容易做到,进程独立性的实现。(进程的独立性可以通过地址空间+页表实现)
因为地址空间的存在,每一个进程都认为自己拥有4GB(32)空间,并且各个区域都是有序的,进而可以通过页表映射到物理内存不同区域,来实现进程的独立性。每一个进程都不知道,也不需要知道其他进程的存在。

4.理解什么是挂起?

我们将我们的代码和数据加载到内存中,加载本质是创建进程,那么是不是非得立马把所有的程序的代码和数据加载到内存中,并创建内核数据结构和建立相关映射关系?答案是否定的。
在最极端的情况下,甚至只有内核结构(task_struct结构体、地址空间、页表,)被创建出来了,映射关系一个都没有。
此时进程的状态就叫做新建状态。当真正调度这个进程的时候,才将进程的代码和数据加载到内存中,设置好映射关系。

理论上,可以实现对进程的分批加载,那是不是可以分批换出呢?当然可以。甚至,这个进程短时间内不会被执行,比如正在等待某种非CPU资源,阻塞了,进程的代码和数据被换出,此时的状态叫做挂起!!!
我们知道页表映射的时候,可不仅仅是内存,磁盘中的位置也是可以映射的嗷,所以在执行换出操作时,不一定需要将内存中数据刷新到磁盘中,可以直接释放掉,只需要将页表的映射关系中的位置改到磁盘中对应的数据位置即可。

今天就到这里吧,我们下次再见!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32F1,F4,L1系列禁止JTAG和SW引脚方法

STM32F1系列 程序中在使用到JTAG、SWD的某个IO 时&#xff0c;需要禁用掉相关调试方法后&#xff0c;再配置相应的IO方式。在需要相应的接口配置前使用这些代码。 对于F1系列&#xff0c;调用函数进行专门的禁止。 标准库配置方式&#xff1a; RCC_APB2PeriphClockCmd(RCC_A…

【蓝桥杯嵌入式】LCD屏的原理图解析与代码实现(第十三届省赛为例)——STM32

&#x1f38a;【蓝桥杯嵌入式】专题正在持续更新中&#xff0c;原理图解析✨&#xff0c;各模块分析✨以及历年真题讲解✨都在这儿哦&#xff0c;欢迎大家前往订阅本专题&#xff0c;获取更多详细信息哦&#x1f38f;&#x1f38f;&#x1f38f; &#x1fa94;本系列专栏 - 蓝…

智能家居Homekit系列一智能触摸开关

触摸开关&#xff0c;即通过触摸方式控制的墙壁开关&#xff0c;其感官场景如同我们的触屏手机&#xff0c;只需手指轻轻一点即可达到控制电器的目的&#xff0c;随着人们生活品质的提高&#xff0c;触摸开关将逐渐将换代传统机械按键开关。 触摸开关控制原理 触摸开关我们把…

HNU工训中心: 三人表决器及八人抢答器实验报告

工训中心的牛马实验 三人表决器&#xff1a; 实验目的 1) 辨识数字IC功能说明。 2) 测试数字集成门电路&#xff0c;掌握输出故障排除、使用注意事项。 3) 掌握逻辑函数搭建三人表决器。 2.实验资源 HBE硬件基础电路实验箱、万用表 74LS00与非门、74LS10 三个3输入与非门…

JS 的同步异步、事件循环

js 执行过程&#xff1a;先执行同步代码在执行异步代码案例1: 以下就是 同步代码异步代码&#xff0c;同步代码先执行&#xff0c;异步代码后执行console.log(1); //1 setTimeout(()>{ console.log(3) //2 },10)案例2: 执行顺序console.log(1) //1 setTimeout(()>{ conso…

ChatGTP--事务是否生效?

项目场景&#xff1a; 由于最近在做一个项目的cola代码改造,所以由于cola需要在 service 和 dao层中间加一层>>> gateway,和springcloud中的gateway不一样,这个仅仅是抽象了一层; 思考: 现在我的事务 依然在service中开启,那么我的事务经过了一个gateway后,再次调用d…

死锁/资源分配/银行家算法

一、死锁 1、原因 竞争资源/程序推进顺序不当 2、必要条件 1、互斥条件 2、请求和保持条件 3、不剥夺条件 4、环路等待条件 3、处理死锁基本方法 1、预防死锁(摒弃除1以外的条件) 2、避免死锁(银行家算法) 3、检测死锁(资源分配图) …

机器学习:图神经网络graph neural network

图神经网络 graph neural networks Neural network Graph GNN应用 关系是否可以提供一些额外信息&#xff0c;不止是考虑entity的特征&#xff0c;还可以考虑关系。 基于近朱者赤 近墨者黑的假设 用邻居更新利用信号系统中&#xff0c;先转到频域&#xff0c;再做基于频域的…

I - 太阳轰炸(组合数学Cnk n固定)

2023河南省赛组队训练赛&#xff08;二&#xff09; - Virtual Judge (vjudge.net) 背景&#xff1a;阿塔尼斯&#xff0c;达拉姆的大主教&#xff0c;在艾尔又一次沦陷之后指挥着星灵的最后一艘方舟舰&#xff1a;亚顿之矛。作为艾尔星灵数千年来的智慧结晶&#xff0c;亚顿之…

数据分享|ESA_WorldCover_10m_2020: 2020年的10米土地覆盖数据(WorldCover v100)

2021年10月,欧洲航空局(ESA)发布了2020年的10米土地覆盖数据(WorldCover v100),该数据基于哨兵1号和哨兵2号的数据,包含11个土地覆盖类别,整体精度达到了74.4%,目前在公开可获取的同类型数据产品里具有一定的优势。那么这份数据具体是什么样子,又该如何获取呢?让我们…

ffmpeg.dll丢失怎么办,有什么修复ffmpeg.dll的方法

如果你在运行某些音视频软件或游戏时遇到了“ffmpeg.dll丢失”的错误消息&#xff0c;这意味着你的Windows系统中缺少了ffmpeg.dll文件&#xff0c;这是一个必要的动态链接库&#xff08;DLL&#xff09;文件&#xff0c;用于支持许多音视频软件和游戏的运行。在这篇文章中&…

Ep_计网面试题-本地IP地址怎么一层层向上转换?

将数据加上报头打包在一起形成新的数据包继续往下一层传递。拆包的时候就是把数据包去掉包头作为新数据传给上一层 视频讲解: https://edu.csdn.net/course/detail/38090 点我进入 面试宝典 很多人不知道面试问什么,或者其他的XXGuide,那里边的太多没用的,也没有源码解析,都…

windows go基本环境安装

一.设置go环境变量 sysdm.cpl //go的安装路径 GOROOT=D:\Go //GOPATH 是 Go语言中使用的一个环境变量,它使用绝对路径提供项目的工作目录 GOPATH=D:\Go\gogopath// golang install 我这里选择D:/Go https://golang.google.cn/dl/

uniapp:3分钟搞定在线推送uni.createPushMessage,uni.onPushMessage

安卓端 在线推送功能演示&#xff1a; 1、dcloud后台申请开通uniPush dcloud后台 &#xff08;1&#xff09;&#xff1a;找到我的应用 &#xff08;2&#xff09;&#xff1a;点进去后&#xff0c;各平台信息&#xff0c;点击新增 &#xff08;3&#xff09;&#xff1a;填…

Web前端学习:五 - 练习

四二-四八&#xff1a;baidu糯米 44-48 1、写法1 &#xff08;1&#xff09;a.movie1 .Navigation .recommend .listbanner a.movie1{background: url(img/h_1.jpg) no-repeat 63px 9px;}表示a标签且class为movie1的元素 如&#xff1a; <a href"#" class&quo…

智能家居项目(七)之Libcurl库与HTTPS协议实现人脸识别

目录 一、前言 二、编译openssl支持libcurl的https访问 三、编写人脸识别代码 四、编程实现人脸识别第二次加入图片base64编码 五、总结 一、前言 上一篇文章我们调用libcurl库去访问了百度&#xff0c;访问的是http协议的百度云主页。那么现在我们要基于翔云人工智能平台…

计算机大小端

我们先假定内存结构为上下型的&#xff0c;上代表内存高地址&#xff0c;下代表内存低地址。 电脑读取内存数据时&#xff0c;是从低位地址到高位地址进行读取&#xff08;从下到上&#xff09;。 1、何为大小端 大端&#xff1a;数据的高位字节存放在低地址&#xff0c;数据…

数据库增删改查II

目录 1.约束 1.1null约束 1.2唯一约束 1.3默认值约束 1.4主键约束 1.5外键约束 2.新增 3.查询 3.1聚合查询 3.1.1.聚合函数 3.1.2group by子句 3.1.3 having 3.2联合查询 3.2.1内连接 3.2.2外连接 3.2.3 自连接 3.2.4子查询 3.2.5合并查询 1.约束 1.1null约…

两个适配器网络冲突,限制访问特定网址

两个适配器网络冲突&#xff0c;限制访问特定网址说明命令说明说明 因为工作需要&#xff0c;有线网络访问局域网服务器&#xff0c;限制特别策略访问&#xff0c;如禁止远程。此时如果想要远程&#xff0c;在连接手机热点就可以&#xff0c;但由于两个网络的存在优先级。就出…

五分钟学会接口自动化测试框架

今天&#xff0c;我们来聊聊接口自动化测试是什么&#xff1f;如何开始&#xff1f;接口自动化测试框架怎么做&#xff1f; 自动化测试 自动化测试&#xff0c;这几年行业内的热词&#xff0c;也是测试人员进阶的必备技能&#xff0c;更是软件测试未来发展的趋势。 特别是在…