【内存管理】从程序进入内存开始说起

305 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情 >>

程序进入内存的初期做了什么?

相信看到这篇文章的朋友都是对操作系统非常熟悉的,对内存管理更是不在话下,那么今天咱们就从一段程序在内存中应该被如何管理开始说起。

程序全部存储

咱们想运行一个程度就需要将其调进内存中,启动为进程,才可以被CPU执行。

我们最初的想法是这样子的:比如说打开QQ,就将QQ软件的所有程序都加载进内存。

image.png

其实上图的做法还有一个关键点:QQ程序放在了内存地址为0的地方,在没有特定场景下说这一句话是有点不妥的。

可能会有些朋友有疑惑,这怎么就不好了,内存地址都清清楚楚明明白白地告诉你了,接才来不就是取指执行就好了吗??

随着PC计数器的移动,不断执行。

image.png

其实这里的不妥就恰恰是因为它太清楚明白了,有些时候是装装糊涂更好的。

相信各位朋友都知道内存地址为0的地方存放的是操作系统的程序,那有怎么可以存放QQ呢?这不就是乱套了吗?

就算QQ程序不放在内存地址为0的空闲地方也是不妥的,因为当QQ程序被换出内存,再换进的时候,就不一定还在该处了。

举个栗子:

image.png

由图中可以看出,

  1. QQ出内存
  2. 微信进入内存,并占用了QQ原来的位置
  3. 当QQ再次进入内存的话,就不能在原来的位置了

在这种情况下,如果想执行main()还是到内存地址为40的地方取指令就会出现问题,因为现在是微信的程序在那里。

其实这个问题也挺好解决的,40很明显就是QQ程序内部的一个偏移量嘛,所以我们只需要知道QQ程序在内存中的起始地址就可以计算得到main()的实际地址了。

基址 + 程序内部的偏移量

这些基址的信息会保存在对应进程的PCB中

程序分段存储

其实上面所说的基于基址来取指已经开始接近真实的操作系统了;但是还有一点,在实际的操作系统中并不会将整个程序一起放进内存中。

实际上,在我们电脑内存中,一个程序的状态更多的是这个样子的:

image.png

由图可以看到,一个程序被分成了好几个部分(好几段),每一段的开始地址都是 0(当然啦,这不是真正的内存地址,可以认为是一个相对地址)

image.png

image.png

这样子的话,就需要通过(段号,基址,偏移量)来找到对应的指令或者数据了。

总结

其实上面讲述的,有一个很重要的概念,那就是——重定位。 重定位,顾名思义就是重新确定位置,在内存管理就是程序进入内存的时候需要重新确定程序的地址(不是相对地址)。很重要的一个点就是确定基址,只要基址确定了,在通过偏移量就可以准确地找到对应的指令或者数据。