存在磁盘中的程序,转成汇编指令以后,用 call 40
,表示调用位置为 40 地方的代码。但是程序的执行,是需要将程序加载到内存中实行的,那么此时的 call
要用到的地址,就必须是真实的物理地址,这个过程是如何实现的呢?
先在内存中,找到一段空白的内存。
把程序加载到这一段内存中。
将这段内存的初试地址,记作基地址,写入进程的 PCB
中,那么程序的实际地址就是在这个基地址上进行。这一步叫做地址翻译
。
一般如果是嵌入式系统,他的功能是固定的,每一次程序执行,都是使用固定的内存,那么可以在编译的时候进行翻译,但是大多数情况下,如PC机,因为内存资源比较珍贵,所以要经常把暂时用不到的进程,从内存挪到磁盘中去,用到的时候,再加载回来,这样的话,相当于程序对应的物理地址是要经常变化的,所以一般都是选择 在运行时候,进行地址翻译
在实际的使用过程中,其实并不是将整个的程序,而是分段的放入到内存中。
程序分段是 编译过程 完成的。
这是因为代码的每一段,特点和用途其实是不一样的,比如代码段只读,而动态数组的部分是要动态增长的。比如说动态数组随着增长的过程中,内存不够了,就要把程序挪到一段更大的内存空间中去,如果要把整个的程序都要挪动,那么工作量就比较大了,如果只挪动态数组这一小段,就比较简单了,所以内存要分段。
分段以后,内存地址就要根据 <段号,段内偏移> 来进行地址翻译了。这就构成了 段表
(KDP)
操作系统也可以看成是一个进程,他对应的段表,就叫做 GDT
表。
之所以要引出分段和分度的话题,在于我们上边把程序的段,在内存中到一段空的内内存,放进去,问题在于,如何找?
这些分区,一般来说大小是不相等的,有的是一直就是未分配的空内存,有的是原来有程序运行,但是现在运行完了,把内存释放出来了,这样的话,如何在这些内存中,找一个合适的 内存块
,把程序放进去。
一般来说,有三种策略
例题:
如果操作系统中,有的段很不规则,有时候需要很大的一个内存块,有时候又很小,此时使用那种分区分配算法?
A. 最先适配
B. 最佳适配
C. 最差适配
D. 没有区分
答案:最佳适配
这样存在的问题,即使因为分区的存在,会产生了很多的 内存碎片
,导致了内存的利用率变低。
为了解决内存采用 分区
造成的内存碎片过多,影响内存利用率低的问题,所以采用内存分页的方法。所以要采用分页的方法,即对内存中,每 4k
分成一个页。即最小的颗粒。这样的话,利用率就高了。同样的,这样如何进行查找呢?分区的时候,要通过 程序分段表
,现在就要通过 程序分段表
进行地址翻译。
原文:https://www.cnblogs.com/rush-peng/p/15040083.html