【Linux】进程地址空间

目录

  • 一、回顾我们以前学习的地址空间
  • 二、进程地址空间
  • 三、进程地址空间的作用
  • 四、解决一个地址出现两个值的问题

一、回顾我们以前学习的地址空间

在这里插入图片描述

这个内存布局真是的我们实实在在的内存嘛? 答案是不是的
下面我们来验证

  1 #include<stdio.h>2 #include<assert.h>3 #include<unistd.h>4 5 int myval=100;6 7 int main()8 {9   pid_t id=fork();10   assert(id>=0);11   if(id==0)12   {13     //子进程14     myval=200;   //修改myval的值15     while(1)16     {17       printf("我是子进程,我的pid是:%d,我的父进程是:%d,myval: %d, &myval: %p\n",getpid(),getppid(),myval,&myval);18       sleep(1);19     }20   }else if(id>0)21   {22     //父进程23     while(1)24     {25       printf("我是父进程,我的pid是:%d,我的父进程是:%d,myval: %d, &myval: %p\n",getpid(),getppid(),myval,&myval);                                                                        26       sleep(1);27     }28   }29 30   return 0;31 }

在这里插入图片描述

可以看到,父进程和子进程中的g_val的地址是一摸一样的,那么按理说将子进程中的g_val改变后,由于他们使用的是一块空间,所以父进程中的g_val的值也应该改变,可这里为什么没有变化??

如果C/C++打印出来的地址是物理内存的地址,这种现象绝不可能存在!而这里使用的地址是虚拟地址。

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

所以最上面那张图应该叫做,进程虚拟地址空间

二、进程地址空间

每个进程都有一个地址空间,都认为自己在独占物理内存。而这个地址空间在内核中是一个结构体 struct mm_struct.

mm_struct 中的分布类似下面这种:

struct mm_struct {unsigned int code_start;  //地址空间上进行区域划分时,对应的线性位置,称为虚拟地址unsigned int code_end;unsigned int init_data_start;unsigned int init_data_end;unsigned int uninit_data_start;unsigned int uninit_data_end ;unsigned int heap_start;unsigned int heap_end;unsigned int stack_start;unsigned int stack end;
}


虽然这里只有start和end,但每个进程都可以认为mm_struct代表整个内存的所有的地址为0x0000…000~0xFFFF…FFF(即每个进程都认为自己拥有4GB的空间,至于到底有没有,是OS要做的事)

真实内存的样子

在这里插入图片描述

页表:是一种特殊的数据结构,放在系统空间的页表区,存放逻辑页与物理页帧的对应关系。 每一个进程都拥有一个自己的页表,PCB表中有指针指向页表。

三、进程地址空间的作用

1.防止访问权限越界
通过添加一层软件层,完成有效的对进程操作内存进行权限管理,本质目的是为了保护物理内存以及各个进程的数据安全。
在这里插入图片描述

2.将内存申请和内存使用的概念划分清楚
通过虚拟地址空间,来屏蔽底层申请内存的过程,达到进程读写内存和OS申请内存管理操作,进行软件上面的分离。
在这里插入图片描述

进程A想申请1000字节空间,进程A马上就能使用这1000字节吗?这是不一定的,可能会存在暂时不会全部使用的情况。

在OS角度,如果空间马上给进程A,就意味着整个系统会有一部分空间本来可以给其他进程立即使用,先在却被进程A闲置着。

这样就会存在空间浪费的情况。操作系统不允许出现浪费和不高效的行为

所以在这种情况下,OS会在进程A使用空间的时候才将内存申请给进程A。(相当于是类似写时拷贝的思想)

3.站在CPU和应用层的角度,进程同意可以看作统一使用4GB空间,而且每个空间区域的相对位置是比较确定的。

如果同时存在多个进程,而每个进程代码的其实位置是不确定的,那么CPU在执行时,需要找到代码在哪里,比较混乱。

而使用虚拟地址空间和页表的方式,将内存划分为代码段、常量区、堆、栈等区域,CPU执行进程时,每次从同一个位置开始即可,而不同的进程通过不同的页表映射到自己的物理内存中存放代码和数据的位置,提高了CPU的执行效率。

所以通过虚拟地址和页表,程序的代码和数据可以被加载到物理内存的任意位置!!极大的减少内存管理的负担。

OS最终这样的目的,为了达到一个目标:每个进程都认为自己是独占系统资源的。

四、解决一个地址出现两个值的问题

在开始那段代码中,我们可以看到myval的值在被子进程修改后,父进程值没有改变,同时打印出来的myval的地址相同,出现了一个地址两个值的情况,我们来解决。

在这里插入图片描述

子进程在创建时会以父进程为模板,即能够拷贝父进程的地方就拷贝,例如虚拟地址,只读区的映射关系(代码共享)。

所以子进程和父进程的虚拟地址是相同的,而页表的映射关系是不同的,所以他们的物理地址也不同。

所以就出现了,子进程改变myval的值,而父进程不变,但打印出的地址却是一样的情况了

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库操作不再困难,MyBatis动态Sql标签解析

系列文章目录 MyBatis缓存原理 Mybatis的CachingExecutor与二级缓存 Mybatis plugin 的使用及原理 MyBatis四大组件Executor、StatementHandler、ParameterHandler、ResultSetHandler 详解 MyBatisSpringboot 启动到SQL执行全流程 数据库操作不再困难&#xff0c;MyBatis动态S…

YOLOv5复现过程出现的问题(关于数据集路径)dataset not found

YOLOv5复现过程出现的问题&#xff08;关于数据集路径&#xff09; 在复现YOLOv5时&#xff0c;按照唐老师的教程&#xff08; https://www.bilibili.com/video/BV11K41167Ar?t122.1&p63&#xff09;下载好了数据集&#xff08;MaskWearing就是检测口罩的一个&#xff0c;…

AT89C51单片机实现单片机串口互动(中断方式,单片机--单片机,应答)

说一下功能&#xff1a;客户机发送0x01到服务机 2服务单片机应答0xf2到客户机 3客户机接收到0xf2,发送信息153432这6个数字到服务机 4client发送完信息后发送0xaa结束通信 5server接收到0xaa后回复0xaa结束通信&#xff0c;从此老死不相往来 看代码&#xff1a; //发送端…

订货系统怎么选?从这四个方面筛选错不了(一)

选择适合的订货系统对企业来说是一个重要且复杂的决策。一个优秀的订货系统可以提高供应链的运作效率、降低成本&#xff0c;并帮助企业更好地管理库存和订单。如果不知道从那几方面做选择&#xff0c;我们可以简单从四个方面进行筛选&#xff0c;这样一般错不了&#xff0c;今…

list

目录 迭代器 介绍 种类 本质 介绍 模拟实现 注意点 代码 迭代器 介绍 在C中&#xff0c;迭代器&#xff08;Iterators&#xff09;是一种用于遍历容器&#xff08;如数组、vector、list等&#xff09;中元素的工具 无论容器的具体实现细节如何,访问容器中的元素的方…

语聚AI如何通过对话方式让AI助手执行应用软件

1 什么是应用助手&#xff1f; 应用助手可以通过对话的方式让AI助手执行应用软件的操作。 例如&#xff0c;您可以调用“Bing搜索引擎搜索”热门信息&#xff0c;然后根据这些信息总结内容。 也可以使用“抖音”应用&#xff0c;搜索热门抖音视频&#xff0c;并根据热门视频生…

Python爱心光波

文章目录 前言Turtle入门简单案例入门函数 爱心光波程序设计程序分析 尾声 前言 七夕要来啦&#xff0c;博主在闲暇之余创作了一个爱心光波&#xff0c;感兴趣的小伙伴们快来看看吧&#xff01; Turtle入门 Turtle 是一个简单而直观的绘图工具&#xff0c;它可以帮助你通过简…

Stable Diffusion WebUI 从零基础到入门

本文主要介绍Stable Diffusion WebUI的实际操作方法&#xff0c;涵盖prompt推导、lora模型、vae模型和controlNet应用等内容&#xff0c;并给出了可操作的文生图、图生图实战示例。适合对Stable Diffusion感兴趣&#xff0c;但又对Stable Diffusion WebUI使用感到困惑的同学&am…

【Apollo】推动创新:探索阿波罗自动驾驶的进步(含安装 Apollo的详细教程)

前言 Apollo (阿波罗)是一个开放的、完整的、安全的平台&#xff0c;将帮助汽车行业及自动驾驶领域的合作伙伴结合车辆和硬件系统&#xff0c;快速搭建一套属于自己的自动驾驶系统。 开放能力、共享资源、加速创新、持续共赢是 Apollo 开放平台的口号。百度把自己所拥有的强大、…

UE4/UE5 照明构建失败 “Lightmass crashed”解决“数组索引越界”

在构建全局光照时,经常会出现“Lightmass crashed”的错误,导致光照构建失败。本文将分析这一问题的原因,并给出解决建议。 UE4 版本4.26 报错如下: <None> === Lightmass crashed: === Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:d:\build…

根据二叉树创建字符串

题目:给你二叉树的根节点 root &#xff0c;请你采用前序遍历的方式&#xff0c;将二叉树转化为一个由括号和整数组成的字符串&#xff0c;返回构造出的字符串。 空节点使用一对空括号对 "()" 表示&#xff0c;转化后需要省略所有不影响字符串与原始二叉树之间的一对…

Linux查看GPU显卡/CPU内存/硬盘信息

显卡信息命令/CPU内存/硬盘 1.显卡2、CPU内存3、硬盘 1.显卡 nvidia-smi nvidia-smi&#xff08;显示一次当前GPU占用情况&#xff09; nvidia-smi -l&#xff08;每秒刷新一次并显示&#xff09; watch -n 5 nvidia-smi &#xff08;其中&#xff0c;5表示每隔6秒刷新一次终端…