Linux:进程地址空间

目录

1.程序地址空间 

2.进程地址空间


1.程序地址空间 

我们在讲C/C++语言的时候,32位平台下,我们见过这样的空间布局图

我们来验证一下这张图的正确性:

  int un_gval;
  int init_gval=100;
  
  int main(int argc, char* argv[],char* env[])
  {
      //代码区
      printf("code addr: %p\n",main);
      //字符常量区
      const char *str = "hello Linux";
      //*str = 'h';//不能修改因为字符常量区是被写入到代码区的,而代码区不能被修改
      printf("read only char addr: %p\n",str);
      //已初始化全局变量区
      printf("init global value addr: %p\n",&init_gval);
      
      //所谓的静态区就是已初始化全局变量区
      static int a ;   
      printf("stack addr: %p\n",&a);

      //已初始化全局变量区
      printf("uninit global value addr: %p\n",&un_gval);
      //堆区
      char *heap1 = (char*)malloc(100);
      char *heap2 = (char*)malloc(100);
      char *heap3 = (char*)malloc(100);
      char *heap4 = (char*)malloc(100);
      char *heap5 = (char*)malloc(100);            
      printf("heap1 addr: %p\n",heap1);//向地址增大方向增长    
      printf("heap2 addr: %p\n",heap2);    
      printf("heap3 addr: %p\n",heap3);    
      printf("heap4 addr: %p\n",heap4);    
      printf("heap5 addr: %p\n",heap5);                                                                                                                   
      //栈区                 
      printf("stack1 addr: %p\n",&heap1);    
      printf("stack2 addr: %p\n",&heap2);
      printf("stack3 addr: %p\n",&heap3);    
      printf("stack4 addr: %p\n",&heap4);   
      printf("stack5 addr: %p\n",&heap5);
  
      //命令行参数
      int i = 0;
      for(;argv[i];i++)
      {
          printf("argv[%d]:%p\n",i,argv[i]);
      }
      //环境变量
      for(i=0;env[i];i++)
      {
          printf("env[%d]:%p\n",i,env[i]);
      }
  
      return 0;
  }

运行结果:

通过观察静态变量的位置,可以认为静态变量就是全局变量,只是静态变量只初始化一次,有作用域的限制。

这里栈区还有一个特点:我们平时定义结构体对象时,我们取地址都是返回整个结构体最低的地址,内部是使用低地址向高地址排列,使用的是起始地址加偏移量的访问方式,但是栈区整体还是先使用高地址在使用低地址。

那么这里就有一个问题了,这张图是真实的物理内存吗?

我们再来验证一下:

  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>

  int g_val = 100;
  
  int main()
  {
      pid_t id = fork();
      
      if(id==0)
      {
          //子进程
          int cnt = 5;
          while(1)
          {
              printf("child, pid:%d, ppid:%d, g_val:%d ,&g_val:%p\n",getpid(),getppid(),g_val,&g_val);
              sleep(1);
              if(cnt == 0)
              {
                  g_val = 200;
                  printf("child change g_val: 100->200\n");
              }
              cnt--;
          }
      }
      else 
      {
          //父进程
          while(1)
          {
              printf("father, pid:%d, ppid:%d, g_val:%d ,&g_val:%p\n",getpid(),getppid(),g_val,&g_val);                                                   
              sleep(1);
          }
  
      }
  
      return 0;
  }

运行上面代码的结果:

什么意思呢?就是我们定义了一个全局变量 g_val,然后我们通过 fork() 创建了一个子进程,让子进程修改了全局变量。我们之前文章中提到过,因为进程之间要保证数据的独立性,父进程的数据子进程也要有一份,而Linux采用写时拷贝,所以在子进程没有修改全局变量值时,父进程和子进程的全局变量地址相同可以理解。但是子进程对全局变量做修改后,写时拷贝应该重新申请一块空间来存放修改后的值,但是根据运行结果我们发现地址还是相同的,子进程全局变量的地址并没有改变,同一个地址竟然读出不同的值?所以我们可以大胆推测我们看到的地址并不是真正的物理地址。

得出结论:

  1. 变量内容不一样,所以父子进程输出的变量绝对不是同一个变量
  2. 但地址值是一样的,说明,该地址绝对不是物理地址!
  3. 在Linux地址下,这种地址叫做 虚拟地址
  4. 我们在用C/C++语言所看到的地址,全部都是虚拟地址/线性地址!物理地址,用户一概看不到,由OS统一管理,OS必须负责将 虚拟地址 转化成 物理地址。

2.进程地址空间

2.1 操作系统如和将虚拟地址转换为物理地址

所以之前说“程序的地址空间”是不准确的,准确的应该说成 进程地址空间 ,那该如何理解呢?

每一个进程运行之后,都会有一个进程地址空间的存在!都要在系统层面都要有自己的页表映射结构

在C/C++中,变量在编译形成可执行程序后,就没有变量名的概念了,都是地址。

2. 什么是地址空间?什么是区域划分?

地址空间也要被OS管理起来!!每一个进程都要有地址空间,系统中,一定要对地址空间做管理。如何管理地址空间呢? 也是通过之前文章提过的先描述,在组织。所以地址空间最终一定是内核的数据结构对象,就是一个内核结构体。

在这个结构体中,分别有每个空间如栈区,堆区的开始和结束位置。

在Linux中,这个进程/虚拟地址空间的东西,叫做:struct mm_struct

struct mm_struct
{
    long code start;
    long code_end;
    long data_start;
    long data_end;
    long heap_start;
    long heap_end; 
    long stack_start;
    long stack_end;
    // ...
}

进程PCB Linux 中的struct task_struct 中也是有指针指向mm_struct的。 

3.为什么要有地址空间

  1. 让进程以统一的视角看待内存,所以任意一个进程,可以通过地址空间+页表可以将乱序的内存数据,变成有序,分门别类的规划好,使得无序边有序
  2. 存在虚拟地址空间,因为页表中有访问权限字段,可以有效的进行进程访问内存的安全检查,比如我们无法修改字符常量的内容,是因为页表访问权限是只读。
  3. 将进程管理和内存管理进行解耦
  4. 通过页表让进程映射到不同的物理内存处,从而实现进程的独立性!所以每一个进程都认为自己可以使用4GB的空间,但是真实的物理空间只有4GB,一个进程并不知道其他进程的存在。
  5. CPU中也有一个CR3寄存器来保存页表的地址,这个地址是真实的物理地址。

扩展问题

我们如果在玩一些大型游戏时,游戏所需要的内存非常大,我们之前学习过 进程 = 内核数据结构体PCB+程序的代码和数据,我们把游戏加载到内存中时,是把所有的代码和数据都拷贝过来吗?根据我们呢的常识,显然不是这样的,因为我们得内存很小,为什么游戏还是可以运行的呢?因为页表中还有是否分配空间和是否有内容的字段,00,表示既没有分配空间也没有内容,我们游戏一次只加载一部分代码和数据,当CPU执行完这段代码时,要执行下面代码,操作系统就会将上面字段改为00,出现缺页中断,然后再去磁盘中拷贝接下来的代码和数据,释放执行完的代码和数据,这样就可以使得我们得游戏可以正常运行。

本篇结束!

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

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

相关文章

C语言之变量的存储方式和生存周期

一、变量的存储方式 C语言变量的存储有两种方式&#xff1a;静态存储方式和动态存储方式&#xff0c;相应的生产期也有两种&#xff1a;静态生存期和自动生存期。 ①静态存储方式&#xff1a;在程序运行前为变量内存分配内存&#xff0c;在程序结束后回收变量的内存。&#x…

java-sec-code中重定向

重定向 状态码3xx 存在问题的代码段 GetMapping("/redirect") public String redirect(RequestParam("url") String url) {return "redirect:" url; }用户访问/redirect路径时&#xff0c;redirect方法会获取web请求中的url参数内容&#xff0…

文化传媒企业网站建设的效果如何

文化传媒业可以细分为多个类目&#xff0c;如企业营销宣传、明星包装、主播打造、马戏团、动漫等&#xff0c;这些都有很高的市场需求度&#xff0c;尤其近些年互联网深入各个行业&#xff0c;线上发展尤为重要&#xff0c;也促进了文化传媒业的发展。 同时该行业需求者&#…

React脚手架搭建

React脚手架 脚手架&#xff1a;可以快速构建项目的基本架构。 脚手架安装命令 可全局安装脚手架 创建项目 来到当前目录下 create-react-app 项目名&#xff08;不要大写字母&#xff09; 运行项目 进到项目里&#xff0c;在项目目录下&#xff0c;执行 npm start &#xff…

FC-13A(用于汽车应用的kHz范围晶体单元,低轮廓贴片)

FC-13A晶体非常适合用在汽车导航系统设计中的应用&#xff0c;是一种具有优异的频率性能和AEC-Q200标准认证的汽车工业级高精度晶体,FC-13A是一款尺寸为3.2 1.5 0.9mm&#xff0c;频率范围32.768KHz耐高温晶振&#xff0c;频率温度系数仅为-0.04ppm/℃&#xff0c;并且其老化…

总结一些vue3小知识2

1.el-tree-select和el-tree组件报错&#xff08;有的下拉选项选择不了&#xff0c;一点击就报错&#xff0c;但是有的却能选择&#xff0c;不会报错&#xff09; 原因:就如同v-for一样&#xff0c;需要添加key才不会出现渲染错误&#xff0c;而el-tree-select和el-tree组件需要…

Python数据科学视频讲解:Python集合

2.14 Python集合 视频为《Python数据科学应用从入门到精通》张甜 杨维忠 清华大学出版社一书的随书赠送视频讲解2.14节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。内容涵盖数据科学应用的全流程&#xff0c;包括数据科学应用…

基于YOLOv8深度学习的西红柿成熟度检测系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

【后端学前端】第四天 css动画 垂直轮播效果(css变量、位移缩放动画、动画延迟)

1、学习信息 视频地址&#xff1a;css动画 垂直轮播效果&#xff08;css变量、位移缩放动画、动画延迟&#xff09;_哔哩哔哩_bilibili 2、源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title…

Java基础语法之抽象类和接口

抽象类 什么是抽象类 并不是所有的类都是用来描述对象的&#xff0c;这样的类就是抽象类 例如&#xff0c;矩形&#xff0c;三角形都是图形&#xff0c;但图形类无法去描述具体图形&#xff0c;所以它的draw方法无法具体实现&#xff0c;这个方法就可以没设计成抽象方法&…

【漏洞复现】Node.js 目录穿越漏洞(CVE-2017-14849)

文章目录 1.1、漏洞描述1.2、影响版本1.3、漏洞复现1、基础环境2、漏洞验证3、漏洞分析 1.4、参考 1.1、漏洞描述 原因是 Node.js 8.5.0 对目录进行normalize操作时出现了逻辑错误&#xff0c;导致向上层跳跃的时候&#xff08;如../../../../../../etc/passwd&#xff09;&am…

闲人闲谈PS之四十九——PLM和SAP集成常见的问题

惯例闲话&#xff1a;天气突变&#xff0c;没想到珠三角也骤降了10几度&#xff0c;昨晚还吹风扇模式&#xff0c;早上起来一下子感觉丝丝凉意。闲人还是喜欢冬天&#xff0c;冷&#xff0c;能让人思维清晰&#xff0c;提高工作效率。趁着天气适宜&#xff0c;赶紧加班擦屁股去…

关于pycharm无法进入base界面的问题

问题&#xff1a;terminal输入activate无法进入base 解决方案 1.Cortana这边找到Anaconda Prompt右击进入文件所在位置 2. 右击进入属性 3. 复制cmd.exe开始到最后的路径 cmd.exe "/K" C:\ProgramData\anaconda3\Scripts\activate.bat C:\ProgramData\anaconda3 …

Python语言学习笔记之八(文件IO)

本课程对于有其它语言基础的开发人员可以参考和学习&#xff0c;同时也是记录下来&#xff0c;为个人学习使用&#xff0c;文档中有此不当之处&#xff0c;请谅解。 1、什么是文件I/O 在Python中&#xff0c;文件IO&#xff08;输人/输出)是指与文件进行交互的过程。这包括读…

JMESPath语言

JMESPath&#xff08;JSON Matching Expression Path&#xff09; 一种查询语言。 主要用于从JSON文档中检索和过滤数据。 通过写表达式提取和处理JSON数据&#xff0c;而无需编写复杂的代码。 功能&#xff1a;数据提取、过滤、转换、排序。 场景&#xff1a;处理API响应…

【谭浩强C程序设计精讲 1】数据类型、常量与变量

文章目录 3.1 C 的数据类型3.2 常量与变量3.2.1 常量和符号常量3.2.2 变量 3.1 C 的数据类型 C语言的数据结构是以数据类型形式出现的。C的数据类型如下&#xff1a; C语言中数据有常量与变量之分&#xff0c;它们分别属于以上这些类型。由以上这些数据类型还可以构成更复杂…

三分钟搞定 || java邮件发送(支持附件,多发)

1.添加Maven依赖 <dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><version>1.6.2</version> </dependency><dependency><groupId>cn.hutool</groupId><artifactId>…

图书管理系统jsp + servlet+mysql

图书管理系统 项目使用jsp servletmysql实现&#xff1b; 登陆注册 首页 首页显示图书信息 图书管理 1添加书籍 2查询书籍 3预览书籍 4修改书籍 用户管理 1查询用户 2修改用户 3 删除用户 链接&#xff1a;https://pan.baidu.com/s/1QXK--ypb6OadbmKFlc0jUQ

跨域的解决方式(java后端)

文章目录 一、跨域介绍1、什么是跨域2、为什么会产生跨域3、禁止跨域的原因 二、简单请求和非简单请求1、简单请求1.1、什么时简单请求1.2、简单请求基础流程 2、非简单请求2.1、预检请求2.2、预检请求的回应2.3、浏览器的正常请求和回应 3、自定义跨域过滤器 三、解决方式1、C…

2023年【G2电站锅炉司炉】考试题库及G2电站锅炉司炉考试报名

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 G2电站锅炉司炉考试题库参考答案及G2电站锅炉司炉考试试题解析是安全生产模拟考试一点通题库老师及G2电站锅炉司炉操作证已考过的学员汇总&#xff0c;相对有效帮助G2电站锅炉司炉考试报名学员顺利通过考试。 1、【多…