Linux进程地址空间

一、程序地址空间分布

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、画图进行理解

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

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值