Linux——为什么大佬都将进程地址空间称为虚拟地址空间

作者:小 琛
欢迎转载,请标明出处

我们看到的地址是真实的物理地址吗?

来看一个例子:以下代码中,父子进程同时对一个变量num进行了运算,父进程让其加,子进程让其减,随之打印其地址。

#include "stdio.h"
  2 #include "unistd.h"
  3 #include "sys/types.h"
  4 #include "sys/wait.h"
  5 int main()
  6 {
  7     int num=10;
  8     pid_t pid=fork();
  9     if (pid<0)                                                                                                                
 10     {
 11         perror("fork");
 12         return 0;
 13     }
 14     else if (pid==0)
 15     {
 16         //child
 17         num-=10;
 18         printf("i am child num=[%d],&num=[%p]\n",num,&num);
 19     }
 20     else if (pid>0)
 21     {
            //father
 22         num+=10;
 23         printf("i am father num=[%d],&num=[%p]\n",num,&num);
 24         wait(NULL);
 25     }
 26     return 0;
 27 }

结果如下:
在这里插入图片描述
这里就出现问题了!!!

变量num的值在父进程中被修改为了20,子进程中被修改为了0,但二者竟然使用的是同一个内存空间中的变量???但一个变量怎么可能拥有两种值呢?

虚拟地址空间

因此,我们通常叫的进程地址空间实际上是不合理的,因为它本质是提供给我们读的虚拟地址空间
在内核中,创建一个进程,在内核有了它的PCB,其内存指针指向的本质是其虚拟内存,地址也必然为虚拟地址,而该虚拟地址通过页表映射关系(后续讲解)到物理内存处。
在该例子中,二者对于同一个变量操作,实际上在物理内存中已经有了两块存储地方,分别分别存放两个不同的值,但通过页表映射的虚拟逻辑地址是相同的。

在这里插入图片描述

页表的映射规则

  • 段页式
    将内存视为块分
    1、根据虚拟地址得到段号,进而在段表中得到页内起始地址
    2、根据刚刚得到的页内起始地址和页号得到块号
    3、根据块号和页内偏移在物理内存中找到该地址
    在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值