程序地址空间

 引入

        看这样一段代码

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 
  5 int g_val = 100;
  6 int main()
  7 {
  8 pid_t id = fork();
  9 if(id==0)
 10 {
 11   int cnt = 0;
 12   while(1)
 13   {
 14     printf("child,pid:%d,ppid:%d,g_val:%d,&g_val:%p\n",getpid(),getppid(),g_val,&g_val);
 15     sleep(2);
 16     cnt++;
 17     if(cnt==5)
 18     {
 19       g_val = 200;                          
 20       printf("child change g_val:100->200\n");
 21     }
 22   }                                     
 23                        
 24 }                                                                                                                                                    
 25 else                                                               
 26 {                                                                
 27   while(1)                                                
 28   {                                   
 29     printf("father,pid:%d,ppid:%d,g_val:%d,&g_val:%p\n",getpid(),getppid(),g_val,&g_val);
 30     sleep(2);                                 
 31   }                                                                                                          
 32 }                     
 33   return 0;
 34 }

        运行结果为: 

        我们发现改之前父子进程的g_val的值都是100,更改之后child的g_val是100,father的g_val是200,但是&g_val的地址都是0x60105c,同一个地址怎么可能存储的值不同?

        原因:这个地址一定不是物理地址!这个地址是虚拟地址。


什么是进程地址空间?

进程地址空间的结构组成

栈区:自定义的变量,指针变量,反正是各种变量都是存在栈上,但是指针变量所指向的内容不一定在栈上。

例:

堆区:通过malloc/new申请的空间, 

静态区:(未初始化数据)(初始化数据)全局变量,静态变量。

例题:

int globalVar = 1;

static int staticGlobalVar = 1;

void Test()

{

static int staticVar = 1;

int localVar = 1;



int num1[10] = {1, 2, 3, 4};

char char2[] = "abcd";

char* pChar3 = "abcd";

int* ptr1 = (int*)malloc(sizeof (int)*4);

int* ptr2 = (int*)calloc(4, sizeof(int));

int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);

free (ptr1);

free (ptr3);

}

第一组:

  选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)

  globalVar在哪里?__C__  staticGlobalVar在哪里?__C__

  staticVar在哪里?__C__  localVar在哪里?__A__

  num1 在哪里?__A__

  分析:

  globalVar全局变量在数据段 staticGlobalVar静态全局变量在静态区

  staticVar静态局部变量在静态区  localVar局部变量在栈区

  num1局部变量在栈区

  

  char2在哪里?__A__  *char2在哪里?__A__

  pChar3在哪里?__A__   *pChar3在哪里?__D__

  ptr1在哪里?__A__    *ptr1在哪里?__B__

  分析:

  char2局部变量在栈区  

  char2是一个数组,把后面常量串拷贝过来到数组中,数组在栈上,所以*char2在栈上

  pChar3局部变量在栈区   *pChar3得到的是字符串常量字符在代码段

  ptr1局部变量在栈区     *ptr1得到的是动态申请空间的数据在堆区

第二组:

  sizeof(num1) = __40__;//数组大小,10个整形数据一共40字节

  sizeof(char2) = __5__;//包括\0的空间

  strlen(char2) = __4__;//不包括\0的长度

  sizeof(pChar3) = __4__;//pChar3为指针

  strlen(pChar3) = __4__;//字符串“abcd”的长度,不包括\0的长度

  sizeof(ptr1) = __4__;//ptr1是指针

进程地址空间的本质

        进程地址空间的本质是数据结构,具体到进程中就是特定的数据结构对象。

想象中:

 实际中:

        本质上就是进程地址空间就是一个个结构体连接,每个结构体被赋予了一个十六进制的地址,而进程的PCB属性中有指向进程地址结构体的指针

        每一个进程都存在一个进程地址空间(如上图),4GB(32位平台),操作系统的真实物理空间是4GB,操作系统给每个进程都“画了一张大饼”,给每个进程都分配了4GB的虚拟地址空间。


        如何理解分区?

        本质上还是结构体对数据区域进行了划分,结构体中的属性对分区的开始与结束进行了标记。


        我们的地址空间不具备对我们的代码和数据的保存的能力,它们是保存在物理内存空间的,将进程地址空间上的地址(虚拟地址)转化到物理内存中,进程提供一张映射表——页表

        这张表保存的是地址与地址之间的映射关系,CPU中的CR3通过映射关系来将虚拟地址映射到物理地址。


 引入中的问题

这样我们就可以理解一开始访问地址相同但是访问的数据不同的问题。

        原因就是进程之间具有独立性,访问的虚拟地址相同但是它们虚拟地址空间与物理地址空间直接产生映射的页表不同(映射关系不同),导致了访问地址相同但是访问的数据不同的问题。

以下用图来说明:

        一开始都是同样的映射关系,同一个虚拟地址对应了同一个地址空间。

        但是当子进程写入数据,这时发生了写时拷贝,复制一份数据并修改,这时虽然父和子的虚拟地址不同但是父和子的映射关系改变了,所以读到的数据不同。

为什么要有进程地址空间?(进程地址空间存在的意义)

1.将物理内存从无序变成有序。让进程统一的视角,看待内存。

        说明:对于进程在虚拟地址空间中的排布是十分清晰的(不同的数据在不同的分区有序排列),但是在物理空间中的排布是不得而知的,是混乱的,这时通过页表将虚拟地址空间与物理空间建立起联系,这时我们只用关注虚拟地址空间即可,至于物理空间交给操作系统通过页表进行操作。

2.将进程管理和内存管理进行解耦合。

        说明:OS对物理空间进行管理,进程对自己的虚拟地址空间进行管理,而物理空间和进程地址空间通过一张页表进行映射,这样进程就不会对物理空间进行干扰,它们之间互不干扰!

3.地址空间+页表是保护内存安全的重要手段!
        说明:当进行进行非法操作物理内存的其他数据时,操作系统会进行拦截,这时仅在虚拟地址空间进行了错误的访问修改,而不会在物理空间中进行。例如:野指针进行非法的越界访问修改时进程可能会崩溃,而操作系统不会,原因是操作系统将这种操作拦截,这种操作仅是在进程地址空间中,而不会在物理空间中。

        这也说明了进程之间是具有独立性的,一个进程的崩溃不会影响其他进程。 

解释一些事情:

malloc/new申请内存

1.申请的内存,本质是在哪里申请的?

        进程的虚拟地址空间中申请。

2.申请的内存会直接使用吗?

        不一定,申请了的内存只是虚拟地址空间,当要写入时,操作系统先进行阻拦(缺页中断),去建立虚拟地址空间和物理地址空间的映射放入页表(真正的申请空间),这时操作系统放开阻拦,允许写入。

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

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

相关文章

记一次Flink任务无限期INITIALIZING排查过程

1.前言 环境&#xff1a;Flink-1.16.1&#xff0c;部署模式&#xff1a;Flink On YARN&#xff0c;现象&#xff1a;Flink程序能正常提交到 YARN&#xff0c;Job状态是 RUNNING&#xff0c;而 Task状态一直处于 INITIALIZING&#xff0c;如下图&#xff1a; 通过界面可以看到…

分布式搜索引擎-elasticsearch基础

分布式搜索引擎-elasticsearch基础 1、什么是elasticsearch&#xff1f; elasticsearch是一款非常强大的开源搜索引擎&#xff0c;可以帮助我们从海量数据中快速找到需要的内容。 elasticsearch结合kibana、Logstash、Beats&#xff0c;也就是elastic stack&#xff08;ELK&a…

【问题解决】| 关于vscode调试python文件 报错 且直接运行正常的诡异情况记录

关于python的debug报错&#xff0c;其实很奇怪 首先&#xff0c;对于工作区代码&#xff0c;我们可以通过CtrlShiftP 来切换Python解释器 这样的话&#xff0c;工作区的代码就不会报import error 而且这样的话是可以运行跑通的&#xff0c;但最抽象的一集来了&#xff0c;这…

element-ui radio 组件源码分享

今日简单分享 radio 组件的实现原理&#xff0c;主要从以下三个方面来分享&#xff1a; 1、radio 页面结构 2、radio 组件属性 3、radio 组件方法 一、radio 页面结构 1.1 页面结构如下&#xff1a; 二、radio 属性 2.1 value / v-model 属性&#xff0c;类型为 string / …

DNS——域名系统

TCP/IP提供了通过IP地址来连接到设备的功能&#xff0c;但对用户来讲&#xff0c;记住某台设备的IP地址是相当困难的&#xff0c;因此专门设计了一种字符串形式的主机命名机制&#xff0c;这些主机名与IP地址相对应。在IP地址与主机名之间需要有一种转换和查询机制&#xff0c;…

算法题 — 三个数的最大乘机

三个数的最大乘机 整型数组 nums&#xff0c;在数组中找出由三个数字组成的最大乘机&#xff0c;并输出这个乘积。&#xff08;乘积不会越界&#xff09; 重点考察&#xff1a;线性扫描 排序法&#xff1a; public static void main(String[] args) {System.out.println(so…

Vue.js+SpringBoot开发农村物流配送系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统登录、注册界面2.2 系统功能2.2.1 快递信息管理&#xff1a;2.2.2 位置信息管理&#xff1a;2.2.3 配送人员分配&#xff1a;2.2.4 路线规划&#xff1a;2.2.5 个人中心&#xff1a;2.2.6 退换快递处理&#xff1a;…

FreeROTS day2

总结DMA空闲中断接收数据的使用方法 首先要要选择串口然后配置串口的参数&#xff0c;配置MDA通道选择接受数据&#xff0c;配置空闲中断&#xff0c;定义一个数据接收的容器&#xff0c;启动MDA传输当串口收到数据时MDA将数据传输到容器中,MDA会一直检测是否有数据当有数据并…

《TCP/IP详解 卷一》第15章 TCP数据流与窗口管理

目录 15.1 引言 15.2 交互式通信 15.3 延时确认 15.4 Nagle 算法 15.4.1 延时ACK与Nagle算法结合 15.4.2 禁用Nagle算法 15.5 流量控制与窗口管理 15.5.1 滑动窗口 15.5.2 零窗口与TCP持续计时器 15.5.3 糊涂窗口综合征 15.5.4 大容量缓存与自动调优 15.6 紧急机制…

有一点好看的wordpress外贸独立站模板

手机配件wordpress外贸网站模板 充电器、移动电源、手机膜、手机电池、手机壳、手机转接头等手机配件wordpress外贸网站模板。 https://www.jianzhanpress.com/?p3809 车载电器wordpress外贸网站模板 车载吸尘器、空气净化器、行车记录仪、车载充电器、车载影音导航等车载电…

设计模式—命令模式:探索【命令模式】的奥秘与应用实践!

命令模式 命令模式是一种行为设计模式&#xff0c;它的主要目的是将请求封装成一个对象&#xff0c;从而使得请求的发送者和接收者之间进行解耦。 在命令模式中&#xff0c;命令被封装为一个对象&#xff0c;包含了需要执行的操作以及执行这些操作所需的所有参数。 命令的发送者…

【异常处理】Vue报错 Component template should contain exactly one root element.

问题描述 启动VUE项目后控制台报错&#xff1a; Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.翻译为&#xff1a;组件模板应该只包含一个根元素 查看vue代码&#xff0…

Python实战小项目-骰子模拟器+Turtle绘图

Python实战小项目-骰子模拟器Turtle绘图 骰子模拟器Turtle绘图 骰子模拟器 导入了random模块&#xff0c;该模块提供了生成随机数的功能。 定义了两个变量min_val和max_val&#xff0c;分别表示骰子的最小值和最大值。在这个例子中&#xff0c;骰子的最小值为1&#xff0c;最大…

二维码门楼牌管理系统应用场景:数据管理的智慧新选择

文章目录 前言一、数据管理部门的智慧工具二、助力决策制定与优质服务提供三、二维码门楼牌管理系统的优势四、展望未来 前言 随着科技的飞速发展&#xff0c;二维码门楼牌管理系统正逐渐成为城市管理的智慧新选择。该系统不仅提升了数据管理效率&#xff0c;还为政府和企业提…

blast原理与使用技巧,最全最详细

BLAST 序列比对 在生物信息学领域&#xff0c;序列比对是一项基础而关键的任务。它帮助研究人员识别基因、理解蛋白质功能&#xff0c;并揭示物种之间的进化关系。 本文旨在介绍BLAST&#xff08;Basic Local Alignment Search Tool&#xff09;的原理及其不同变体&#xff0c;…

买不到的数目c++

题目 输入样例&#xff1a; 4 7输出样例&#xff1a; 17 思路 一个字&#xff0c;猜。 一开始不知道怎么做的时候&#xff0c;想要暴力枚举对于特定的包装n, m&#xff0c;最大不能买到的数量maxValue是多少&#xff0c;然后观察性质做优化。那么怎么确定枚举结果是否正确呢…

「词令官网直达」网址导航分享5个最具权威的研究生考研信息平台官方网站

分享5个最具权威的研究生考研信息平台网站 1、中国研究生招生信息网 官网直达入口&#xff1a;打开「词令」关键词口令直达工具&#xff0c;输入词令「中国研究生招生信息网」搜索直达进入中国研究生招生信息网官方网站&#xff1b; 中国研究生招生信息网&#xff08;简称研…

npm ERR! code ERR_INVALID_URL报错解决

这个报错是URL错误&#xff0c;要排除两个点 npm的registry有没有搞错&#xff0c;也就是npm源有没有搞错 打开文件C:/User/<用户名>/.npmrc查看npm设置查看registry的设置有没有格式错误正确设置格式&#xff1a;registry"https://registry.npmmirror.com"或…

搜维尔科技:动作捕捉与数字时尚:Wondar Studios欧莱雅项目

来自意大利的Wondar Studios工作室&#xff0c;是一家制作与动作捕捉技术相关软件和内容的公司&#xff0c;其出品的三维角色动画均由专业动捕系统真实录制制作。 我们很高兴与大家分享Wondar Studios最新的动捕项目&#xff0c;该项目带来了身临其境的虚拟现实体验。他们与巴…

【Spring高级】第2讲:容器实现类

目录 BeanFactory实现BeanDefinition后置处理器单例bean创建后置处理器顺序总结 ApplicationContext实现ClassPathXmlApplicationContextFileSystemXmlApplicationContextAnnotationConfigApplicationContextAnnotationConfigServletWebServerApplicationContext BeanFactory实…