Linux进程地址空间

2023-12-14 12:32:51

一、程序地址空间分布

1、程序地址空间

在我们学习c语言的时候我们认识到常量区、堆区、栈区、代码区等等在内存上分布的区域,并且使用编译器看到了他们的程序空间地址,他们的具体分布如下:
在这里插入图片描述

但是在linux中真的是这样分布的么,下面我们来验证看一下。

2、进行验证程序地址空间

    1 #include<stdio.h>
    2 #include<stdlib.h>
W>  3 int main(int argc,char*argv[],char*env[]){
    4   int a=1;
    5   int b;
W>  6   char*p="hello world";
W>  7   char*p1="hello world1";
W>  8   char*p2="hello world2";
W>  9   char*p3="hello world3";
   10   printf("a:%p\n",&a);
   11   printf("b:%p\n",&b);
   12   printf("heap:%p\n",p);
   13   printf("heap1:%p\n",p1);
   14   printf("heap2:%p\n",p2);
   15   printf("heap3:%p\n",p3);
   16   printf("stack:%p\n",&p);
   17   printf("stack:%p\n",&p1);
   18   printf("stack:%p\n",&p2);
   19   printf("stack:%p\n",&p3);
   20   for(int i=0;argv[i];i++){
   21     printf("argv[%d]:%p\n",i,argv[i]);
   22   }
   23   for(int i=0;env[i];i++){
   24     printf("env[%d]:%p\n",i,env[i]);
   25   }
   26   return 0;                                                                                                                                                                  
   27 }   

在linux中运行后好像确实是向上面的图一样分布的。(但是好像初始化数据的地址空间和未初始化数据的地址空间又没有按上面的图形分布这是为什么?因为通常情况下,变量在内存中是按照它们声明的顺序来分配空间的,但是在实际分配时,编译器可能会进行内存对齐或优化)

在这里插入图片描述

3、在子进程父进程中讨论地址空间

修改val值之前:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int val=0;
  4 int main(){
  5   size_t id=fork();                                                                 
  6   if(id==0){
  7   printf("i am a child process val:%d\n",val);
  8   printf("i am a child process adress:%p\n",&val);
  9   }
 10   printf("i am a father process val:%d\n",val);
 11   printf("i am a father process adress:%p\n",&val);
 12   return 0;
 13 }

在下面执行的结果我们可以看出父子进程的val值和地址都是相同的。
在这里插入图片描述
在子进程中对val值进行改变,如下:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int val=0;
  4 int main(){
  5   size_t id=fork();
  6   if(id==0){
  7     val=100;                                                                        
  8   printf("i am a child process val:%d\n",val);
  9   printf("i am a child process adress:%p\n",&val);
 10   }
 11   printf("i am a father process val:%d\n",val);
 12   printf("i am a father process adress:%p\n",&val);
 13   return 0;
 14 }

我们在下面的运行结果中发现,父子的val值改变了,但是地址还是相同的,这就证明我们所看到的地址并不是真实的物理地址而是虚拟地址。
在这里插入图片描述

二、进程地址空间

1、进程地址空间的简述

所以之前说‘程序的地址空间’是不准确的,准确的应该说成 进程地址空间。
进程地址空间:进程地址空间是OS创建的一个结构题名字叫做mm_struct对虚拟地址空间进行划分其虚拟地址从(0x 00 00 00 00到 oxff ff ff ff)同样的别进程控制块PCB管理起来,每个进程对有自己的进程地址空间,也就是每个进程都认为自己是独占资源认为自己拥有4GB的空间(32位平台下)。所以说进程地址空间其实是一个虚拟地址空间。虚拟地址空间也可以认为是地址空间上进行区域划分时,对应的线性位置虚拟地址!。
虚拟地址空间每个进程都有虚拟地址空间,OS会将虚拟地址通过某种映射关系映射到物理地址上,从而对应到真正的物理地址上。

2、画图进行理解

下面是对进程地址空间的图形理解
在这里插入图片描述

文章来源:https://blog.csdn.net/m0_54427678/article/details/134907201
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。