0%

静态链接和动态链接

gitk是git提供的一个gui工具,可以很清晰地查看搜索提交历史及git相关操作。在终端git仓库目录下输入gitk命令即可使用。

一、基础

  1. 对于C语言开发,编写好的程序代码一般保存在.c文件中,此时.c文件就叫做源文件。要将编写好的程序运行起来,或者说从源文件到目标文件,一般还要经过以下几个阶段:预编译、编译、汇编、链接、加载(装载)、运行,静态链接和动态链接就是链接这一阶段的产物。

    • 链接器是一个独立程序,将一个或多个库或目标文件(先前由编译器或汇编器生成)链接到一块生成可执行程序。
  2. 静态链接

    • 在实际开发过程中,不可能将所有源代码放在一个文件中,一般会根据模块或功能等分类方式将代码保存在多个源文件中。对于大部分应用来说,多个源文件之间不是独立的,而是会存在这相互依赖的关系,如一个源文件可能要调用另一个源文件中定义的函数等。在编译阶段,由于每个源文件都是独立编译的,即每个.c文件会形成一个.o文件,为了满足相互依赖的关系,需要将这些源文件产生的目标文件进行链接从而形成一个可以执行的程序,这个链接的过程就是静态链接,其后缀名一般为.a,win环境下为.lib。简而言之就是在程序执行之前完成所有的组装工作,生成一个可执行的目标文件(win环境下的.exe文件或linux下的可执行文件)。
    • 链接器在链接静态链接库的时候是以目标文件为单位的,比如引用了静态库中的printf()函数,那么链接器就会把库中包含printf()函数的那个目标文件链接进来。一般情况下,静态链接库的的目标文件会包含很多函数,如print、sprintf(实际不一定在同一个文件,只为举例用),如果很多函数都放在一个目标文件中,很多没用的函数都被一起链接进了输出结果中,进而导致空间的浪费。
    • 优缺点
      • 浪费空间
      • 更新困难
      • 执行速度快
  3. 动态链接

    • 动态链接就是把程序按照模块拆分成多个相对独立的部分,运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件,其后缀名一般为.so,win环境下为.dll。简而言之就是在程序已经为了执行被装入内存之后完成链接工作,并且在内存中一般只保留该编译单元的一份拷贝。
      • 装载时动态链接(Load-time Dynamic Linking):在编译之前已经明确知道要调用DLL中的哪几个函数,编译时在目标文件中只保留必要的链接信息而不含DLL函数的代码;当程序执行时,调用函数的时候利用链接信息加载DLL函数代码并在内存中将其链接入调用程序的执行空间中(全部函数加载进内存),其主要目的是便于代码共享。
      • 运行时动态链接(Run-time Dynamic Linking):在编译之前不知道将会调用哪些DLL函数,在运行过程中根据需要决定应调用哪个函数,将其加载到内存中(只加载调用的函数进内存),并标识内存地址,其他程序也可以使用该程序,并用LoadLibrary和GetProcAddress动态获得DLL函数的入口地址(dll在内存中只存在一份)。
    • 优缺点
      • 节省空间
      • 更新简单
      • 执行速度慢

静态链接和动态链接两者最大的区别就在于链接的时机不一样,静态链接是在形成可执行程序前,而动态链接的进行则是在程序执行时。

二、参考

  1. 静态链接
  2. 动态链接