• 【Linux】程序地址空间


    C/C++程序地址空间

    在这里插入图片描述
    思考一个问题,这里的地址是什么地址???

    使用程序打印程序地址空间:

    #include 
    #include 
    #include 
    #include 
    
    int g_unval;
    int g_val = 100;
    
    int main()
    {
      // 验证地址空间
      const char* s = "hello world!";
      printf("code addr: %p\n", main);
      printf("string randonly addr: %p\n", s);
      printf("uninit addr: %p\n", &g_unval);
      printf("init addr: %p\n", &g_val);
      char* heap = (char*)malloc(10);
    
      printf("heap addr: %p\n", heap);
      printf("stack addr: %p\n", &s);
      printf("stack addr: %p\n", &heap);
      int a = 1;
      int b = 2;
    
      printf("stack addr: %p\n", &a);
      printf("stack addr: %p\n", &b);
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述

    还可以发现栈向低地址生长,堆向高地址增长。

    看另外一段代码,使用fork创建子进程,在第3秒的时候改变了子进程的数据,观察父子进程该数据的地址:

    在这里插入图片描述

    在这里插入图片描述

    可以发现数据修改后,父子进程数据的地址还是一样的,但是变量的内容不一样!
    1、变量内容不一样,父子进程输出的变量绝对不是用一个变量。
    2、地址值一样,说明,该地址绝对不是物理地址!
    3、在Linux下,这种地址叫做虚拟地址(线性地址)
    4、所以,我们在C/C++看到的地址,全部都是虚拟地址!用户看不到物理地址,OS必须负责把虚拟地址转成物理地址(通过页表+MMU)

    进程虚拟地址空间

    和进程控制块的思维一样,进程虚拟地址空间也要采用先描述的方式!

    struct mm_struct {
    	int code_start;
    	int code_end;
    	
    	int init_val_start;
    	int init_val_end;
    
    	// ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    每个进程都认为自己有一个地址空间,都认为自己在独占物理内存。每个进程都认为自己有4G,认为地址空间的划分是按照4GB空间去划分的。每个人,都用相同的方式去看待内存。

    代码上,地址空间上进行区域划分时,对应的线性位置 即 虚拟地址

    在这里插入图片描述

    为什么要有地址空间?

    1、通过添加一层软件层,完成有效的对进程操作内存进行风险管理(权限管理),本质目的是为了保护物理内存以及各个进程的数据安全。

    2、将内存申请和内存使用的概念在时间上划分清楚,通过虚拟地址空间,屏蔽OS底层申请内存的过程,达到进程读写内存,OS进行内存管理操作,进行软件上的分类。

    比如,我们申请了1000个字节,我们不一定能立马使用1000个字节。在OS角度,如果这块空间现在给你,意味着会有一部分空间浪费,可以给别人用地现在却被你闲置了!所以只是一张空头支票,等你真的要用的时候,会发生 缺页中断 进行物理内存的申请。
    类似的还有,数据的写时拷贝。

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

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

    这里需要再次区分进程和程序的概念。

    所以回过来看上面的程序,同一个变量的地址相同,其实说的是她的虚拟地址相同,内存不同是因为被映射到了不同的物理空间。如下图所示:

    在这里插入图片描述

  • 相关阅读:
    【JAVA-Day32】精通Java函数:定义、调用和主函数的完整指南
    java-php-python-ssm在线考试系统演示录像2021计算机毕业设计
    ubuntu添加环境变量
    React中的Hooks--useReducer()
    【蓝桥每日一题]-前缀和与差分(保姆级教程 篇1)
    阿里云服务器企业级和入门级实例规格有何区别?如何选择?
    本地生活小程序有什么功能_本地生活小程序的优势
    Git 的基本概念和使用方式
    【网络】内网穿透方案&FRP内网穿透实战(基础版)
    在线考试组卷Word文档导出|废纸篓|支持搜索组员查看练习情况|官网上线
  • 原文地址:https://blog.csdn.net/Joy_Cheung666/article/details/126132069