【Linux】进程虚拟地址空间

进程虚拟地址空间打破了我一直以来对于程序地址空间的认识,它真的好神奇。
我们首先来看一下下面这段代码:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 /*
  4  *定义一个全局变量
  5  *创建子进程
  6  *修改变量值,再取地址,观察地址是否一样
  7  * */
  8 int glo_val=10;
  9 int main()
 10 {
 11   pid_t ret = fork();
 12   if(ret < 0)
 13     return 0;
 14   else if(ret == 0)
 15   {
 16     //child
 17     glo_val = 20;
 18     printf("I am child,glo_val = %d,address = %p\n",glo_val,&glo_val);
 19   }else if(ret > 0)
 20   {
 21     //father 
 22     printf("I am father,glo_val = %d,address = %p\n",glo_val,&glo_val);
 23   }
 24   return 0;
 25 }

我们来看一下它的运行结果:

在这里插入图片描述

是不是很神奇!!!
打印出来的两个地址相同,但是!值不一样!!
就非常奇怪啊,为什么会这个样子呢?难道我拿的地址是假地址?我取地址的方式有误?但是我检查过了,没有毛病,所以这个可能是某个我不知道的知识引起的,于是,我去查了查,下面就给大家解密。

通过上面的程序和它的运行结果,我们可以发现:变量内容不一样,所以父子进程输出的变量绝对不是同一个变量,但是地址值是一样的,说明这个地址肯定不是物理地址!!!打印的这种地址叫做虚拟地址。

操作系统为什么要弄一个虚拟地址出来呢?

提高内存的使用率

虚拟地址:我们用户是看不到物理地址的,那大家可能就有疑问了,我取地址取的不是地址吗?是地址,只不过是虚拟地址,真正的物理地址是由OS统一管理的。OS需要将程序中的虚拟地址转化为物理地址。

进程虚拟地址空间

在32为操作系统下,OS为每一个进程无差别的虚拟出4G的虚拟地址空间,程序在访问内存的时候,访问的是虚拟地址空间,既然是虚拟地址空间,那就不能直接存储数据,存储数据还是得存储在真正的物理空间里,于是OS就需要将虚拟地址空间转化为物理地址进行访问。那怎么转化呢?就使用我们接下来将要提到的页表。

为什么OS要给每一个进程都虚拟出来一个进程虚拟地址空间呢?为什么不直接允许进程访问物理内存呢?

因为各个进程访问同一个内存地址空间,就会不可控,可能会导致越界访问。在有限的内存空间里,进程它是不知道哪块内存是被其他进程使用的,也不知道哪块内存是空闲的。所以,在这种场景下,让进程直接访问物理内存,一定会导致多个进程在访问物理内存时出现混乱。所以,内存由OS统一管理起来,但是又不能采用预先分配内存的方式给进程,因为OS也不清楚进程真正要保存多少数据,不知道分配多少内存给进程合适,于是操作系统就虚拟的给每一个进程分配了4G(32位操作系统下)的地址,这个地址是虚拟的地址。
进程需要保存数据,或者申请内存的时候,操作的都是虚拟地址,让操作系统再给进程进行分配,同时也节省空间,用多少分配多少,这样是不是就很合理。
每一个进程无差别的使用拿到的虚拟地址,OS会将虚拟地址通过页表映射转换为真正的物理地址。

页表映射

进程虚拟地址空间和物理内存之间存在着映射关系,就是页表映射,将虚拟地址分成一页一页的,将物理内存分为一块一块的,通过页表来记录虚拟地址和物理地址的映射关系,页表由页号和页内偏移构成。
我们可以通过虚拟地址+页表的方式来找到物理地址。

  • 虚拟地址 = 页号+页内偏移
  • 页号 = 虚拟地址 / 页的大小
  • 页内偏移 = 虚拟地址 % 页的大小

这样我们就能根据页的起始地址找到具体的物理地址。
同时需要注意的是,在进行内存分配的时候,我们不采取连续分配的方式,而是采用一页一页离散分配的方式,主要是为了防止产生内存碎片。

最后总结一下:

  • 每个进程都有独立的虚拟地址空间,进程访问的并不是真正的物理地址。
  • 虚拟地址可以通过每个进程上面的页表与物理地址进程映射,获得真正的物理地址。。
  • 页表在每个进程的内核虚拟地址空间里
  • 如果虚拟地址对应的物理地址不在内存当中,就会产生缺页中断,真正分配物理地址,同时更新进程的页表,如果此时物理内存已经耗尽,则根据内存替换算法淘汰部分页面至物理磁盘中。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值