Linux进程地址空间

1.问题的引入

如下的在centos的版本下,Linux程序如下:

   #include<stdio.h>
   #include<unistd.h>
   #include<stdlib.h>
   #include<sys/types.h>
   
   int g_val=10;
   
   int main()
   {
      pid_t id=fork();                                                          
        if(id==0)
       {
          g_val=20;
         printf("g_val=%d address:%p\n",g_val,&g_val);
       }
       else
        {
         printf("g_val=%d address:%p\n",g_val,&g_val);
       }
     return 0; }

当我们使用fork函数创建子进程的时候,改变了全局变量,应该会出现两个不同的地址,结果让人很吃惊

两个不同的全局变量,出现不同的值,地址却是相同的,这是不是很奇怪,其实这是进程的虚拟地址的原因。

2.进程虚拟地址空间

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

那虚拟地址转化成物理地址是通过什么转化的呢,答案是页表。

页表中的虚拟地址可以映射对应的物理地址

所以我们通过图来看这个过程就可以理解虚拟地址了

这是父进程的pcb中有对应的虚拟地址,在虚拟地址中的对应区域中创建一个全局变量

创建子进程后,当我们需要改变父进程的数据时,会发生写时拷贝,在物理内存中开辟空间拷贝g_val全局变量。

这样我们就可以看到不同的值却出现一样的地址。

这样做的目的有三个:

1.让进程以统一的视角看待内存,保证每个对应的数据和代码在不同的区域,方便管理。

2.增加进程的虚拟空间可以让我们访问内存的时候,增加一个转换的过程,在这个转化的过程中,可以对我们的寻址请求进行审查,所以一旦异常访问,直接拦截,该请求不会到达物理内存,保护物理内存。

3.因为有地址空间和页表的存在,将进程管理模块,和内存管理模块进行解耦合。


今天是1024程序员节,祝所有的程序员可以健健康康,赚大米,我今天发表的博客正好赶上了,我很感谢我的女朋友小泽和我的家人一直陪在我的身边,我会努力成为更好的自己,陪着他们。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值