程序的装入与链接(动、静态重定位)

用户程序要在系统中运行,必须要把它装入内存,然后再将其转变成一个可执行程序。

 

用户程序变为可执行程序都需要执行以下步骤:

      程序的装入与链接(动、静态重定位)_第1张图片

  •       编译:由编译程序进行编译,形成若干个目标模块。    (编译程序执行)

  •       链接:由链接程序将编译好的若干个目标模块以及它们所需要的若干个库函数链接在一起。形成转入模块                                                                       (链接程序执行)

  •       装入:由装入程序将链接好的转入模块转入到内存中。(装入程序执行)

程序的链接

由于用户不知道内存具体地址到底是多少,所以一般编写的地址都是相对地址,都是相对于每个模块中的起始地址,通常都是0。而且在链接之前,彼此是相互独立的。

静态链接

首先看看第一个问题:

          链接多个模块为一个模块,各个模块使用的都是相对地址,其起始地址都是0,在链接成一块后,除了第一个起始地址为0,其后面的起始地址都应该发生变化。

          第二个问题是要变换外部调用符号。如下图A中的CALL B 和B中的CALL C要变成相对地址

如下图:源程序编译后得到三个目标模块A、B、C,长度分别为L、M、N,链接后形成右侧的装入模块:

程序的装入与链接(动、静态重定位)_第2张图片

 装入时动态链接

顾名思义,就是在程序装入时进行链接,具体操作还是和上图一样,就是时机不同“而已”

优点:

  •          便于修改和更新:如果是静态链接,再修改或更新某个目标模块,则需要重新打开装入模块。这很明显低效,而且有时是不可能的。若采用动态连接方式,由于各目标模块是分开存放的,所以先对静态来说是件很容易的事情。

  •          便于实现目标模块的共享:静态链接是把各模块都复制一遍,形成装入模块,无法实现对目标模块的共享。动态链接OS就很容易的将一个目标模块链接到几个应用模块上。实现对多个应用程序对该模块的共享。

运行时动态链接

       采用上述链接方式还存在一个问题,那就是在许多情况下,应用程序在运行时,每次要运行的模块可能是不相同的,而且无法预知会用到哪些模块,所以在是想上述方法进行链接时,只能将所有可能用到的模块全部装入内存,这显然是低效的。比较典型的就是错误处理的模块,如果整个运行不出错,就不会用到该模块。 

       所以推出了运行时动态链接,是对某些模块的链接推迟到执行时才进行链接。亦即,在执行过程中,若发现一个即将调用的模块尚未在内存中,则立即通知OS去找到该模块,并将其装入内存。

优点:加快程序的装入过程。节省大量的内存空间

       

程序的装入(将程序装入内存以待执行)
      首先看看单个模块的装入方式

        1.绝对装入(根据程序指定装入指定内存)适用于单道程序环境。

        2.可重定位装入

        多道程序环境下,编译程序不可能预知经编译后所得到的目标模块应存放在内存的何处,因此在编译的时候给出的起始地址都是从0开始计算的,其他地址都是相对于0开始的。不能再用绝对装入方式装入,而应采用可重定位方式装入。

这样装入会产生一个问题:装入后地址访问导致数据错误,因为逻辑地址(自己程序中定的相对于起始地址的相对地址)与实际物理地址不匹配。

解决办法:在程序装入后,将之前的0起始地址变为装入内存后的起始地址(地址重定位)。

         3.动态运行时的装入方式

          由于上述可重定位装入还存在一个问题,就是在程序如果在运行时在内存中发生移动,就会发生错误。在这种情况下,就应采用动态运行时装入。是指在把装入模块装入内存后,并不是立即把装入模块中的逻辑地址转换位物理地址,而是在程序真正执行的时候才进行地址转换。

          

总结:

程序的装入与链接(动、静态重定位)_第3张图片

        

你可能感兴趣的:(操作系统)