进程地址空间

引例

#include <stdio.h>
#include <unistd.h>

int main()
{ 
  int test_num = 0;
  pid_t pid = fork();
  if(pid == 0)
  {
    test_num =100;
    printf("子进程test_num的值%d,test_num的地址%p\n",test_num,&test_num);
  }
  else if(pid > 0)
  {
    printf("父进程test_num的值%d,test_num的地址%p\n",test_num,&test_num);
    sleep(1);
  }
  return 0;
}

在这里插入图片描述
观看这个代码,父子进程中的相同变量可以存储两个不同的值?带着这个问题往下看
首先我们先回顾一下那个在C语言和C++学习中的“内存空间分布图”
在这里插入图片描述
根据计算机组成原理的知识,在同一个存储单元是不可能存储两个值的,所以我大胆推出,我之前C/C++学的指针地址和%p打印出来的地址都不会物理地址,而是虚拟地址/线性地址。

static关键字对变量的影响

在这里插入图片描述
从这个代码可以得出,被static修饰之后的变量c,生命周期从栈区变到了全局数据区。注意:static的修饰只改变了生命周期没有改变作用域,就是变量a虽然放在了全局数据区,但是只能在main函数使用(作用域)

什么是地址空间?

物理地址

在计算机硬件存储中,如图:在这里插入图片描述数据的存储空间由这样的一个金字塔形成越上面的存取速度越快,越下面的存取数据越慢,为什么这样设计呢?1.节省成本,如果这个电脑存储都用cache,价格昂贵,无法让计算机平民化,如果只用存取速度慢的,就会大大的影响CPU的速度。就好像你在微信发文件给a同学,你的网络速度快,而他的网络速度慢,进而导致文件传输慢一个道理。
这里讲得地址空间是指内存,而在电路中,以高低电平作为数据表示,一组二进制排列组合则表示一个存储单元,你的地址总线返回一般为[0,2^32),结论1:物理地址指的是你的二进制排列组合数。

如何理解地址划分

问:对于上面内存空间分布图中,不同空间的分布用什么作用?本质上就是作用域和生命周期的区别。而在操作系统中,我们一直都是秉持的先描述后组织的理念,那本质上就是对内存建立一个结构体,在里面记录每一个区域的空间开始和空间结束。
结论2:用先描述后组织的理念,地址划分其实就是结构体
根据这个两个点的得出总结:进程地址空间是一个结构体,是一个操作物理地址结构体
到这里我们不禁引出一个新的问题:如何操作?

页表

对于这个点,我不过多于深究计算机组成原理的概念知识。我们暂时的认为,这个就是一个表,上面有四列,每一个列的标题为,虚拟地址,物理地址,权限(是否有读取权限),状态(是否载入完毕)
在这里插入图片描述
比如,现在我用C语言写了一句char* str = “hello” ,然后就在页表的虚拟地址位置写入字符常量区的地址,而linux的内存管理看到这是字符串常量区的地址值,也会相应的写入对应的物理位置,并在权限那一栏中记录这个变量是只读的,并在状态中记录写入完毕。

回答引例问题

现在我们在回过头来看引例的问题
在这里插入图片描述
我们声明了两个相同虚拟地址的变量,对于这种现象页表会去检查,如果有相同的他就会把另一个的物理地址指向不同的地方,分开存储,这样就解释了引例中,为什么父子进程变量名一样,地址一样,而存取的值却不一样的现象。

再谈独立性

在以往文章中,我们说进程由pcb+代码数据组成的,在这里应该再去扩展,进程是由PCB、进程地址空间、页表+代码和数据。而独立性则代表每一个进程都会有他自己独立的进程地址空间、pcb、页表。

为什么会有地址空间

1.让进程以统一的视角看待内存。
2.增加进程虚拟地址空间可以让我们访问内存的时候,增加一个转换的过程,在这个转化的过程中,可以对我们的寻址请求进行审查,所以一旦异常访问,直接拦截,该请求不会到达物理内存,保护物理内存
3.因为有地址空间和页表的存在,将进程管理模块,和内存管理模块进行解耦合

操作系统如何将大文件从硬盘移动到内存中

共识:现代操作系统,几乎不做任何浪费空间和浪费时间的事情,所以操作系统对大文件可以实现分批加载,计算机会使用惰性加载的方式,就是你要用多少内存,我就给你多少内存,不会给多也不会给少。
这种时候会先给你填写虚拟地址,物理地址先不填,在状态那一栏标志还没有加载完。等待加载完毕,再把物理地址那一栏填上。如果显示没有加载完,他会给你缺页中断,等到内存足够,或者cpu时间片轮到你这个进程时候,进入你的缺页中断,接着完成你还没有完成的事。
这样我们就可以实现边使用边加载。
当我们创建进程的时候,实现创建内核数据结构再去加载对应的可执行程序。

总结

在C语言中学习地址空间分布,不是内存,而是进程地址空间本质上是一个结构体用于记录变量的虚拟地址,操作系统通过虚拟地址和页表的映射去物理内存中寻找对应的数据,每一个进程都会有他对应的pcb结构体、进程地址空间、页表,保证每个进程的独立性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值