精华内容
下载资源
问答
  • SDK之动态链接库开发—基本概念

    千次阅读 2017-09-19 15:14:50
    1、静态链接库和动态链接库 用静态库的话,目标电脑上如果没有这个文件的话能正常使用程序;用动态库的话,目标电脑上必须要有这个文件才能正常使用程序,或者你可以要发布程序的时候将这个文件一起打包。   2、...

    1、静态链接库和动态链接库

    用静态库的话,目标电脑上如果没有这个文件的话能正常使用程序;用动态库的话,目标电脑上必须要有这个文件才能正常使用程序,或者你可以要发布程序的时候将这个文件一起打包。

     

    2、动态链接库的连接方式:隐式链接和显式加载

    隐式链接就是在程序开始执行时就将DLL文件加载到应用程序当中,在链接时需要用到lib文件,才能直接通过DLL中导出的函数名来调用函数;显式加载则是在运行时加入,在代码中需要显式调用LoadLibrary()和FreeLibrary(),而且在调用dll中导出的函数时,需要使用GetProcAddress()获取想要引入的函数。

    两种方式对于你的程序调用动态库时没有任何区别,只是你在编程时,步骤是不一样的:显式调用麻烦了点,但可以没有相应的lib库;隐式调用,使用起来比较简单,有函数的声明就可以了,但必须有lib库。

    隐式加载默认是加载到内存中的,始终占用内存;显式加载,你加载时占用内存,释放了就不占用内存了。如果该DLL已经载入,loadlibrary只是会增加一个引用计数,相同,freelibrary也只是减少引用计数,如果引用计数为0时,DLL才从内存中移除。

    显式和隐式只是对于代码编写时来说的,最后产生的可执行程序,不管是显式和隐式,都是用loadlibrary载入的。显式与隐式不是用在这些方面的,显式加载适合需要动态的选用DLL的情况。使用导出类和导出结构体的时候,隐式链接较为方便,而显式链接则很麻烦。

     

    显式链接库的好处:在需要的时候加载动态链接库某个函数。

    隐式链接的缺点:使用比较简单,在程序的其他部分可以任意使用函数,但是当程序访问十来个dll动态链接库的时候,此时如果都使用隐式链接的时候,启动此程序的时候,这十来个动态链接库都需要加载到内存,映射到内存的地址空间,这就会加大进程的启动时间,而且程序运行过程中,只是在某个条件下使用某个函数,如果使用隐式链接会造成资源的浪费。这样需要采用显式(动态加载)的方式。

     

    3、def和extern"C"

    如果DLL使用的是def文件,要删除TestDll.h文件中关键字extern"C"。

     

    4、__declspec(dllimport)__declspec(dllexport)

    不使用__declspec(dllimport) 也能正确编译代码,但使用 __declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于 DLL 中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨 DLL 边界的函数调用中。但是,必须使用__declspec(dllimport) 才能导入 DLL 中使用的变量。

     

     

     

     

    5、动态载入(显式链接)DLL需要的三个函数

    (LoadLibrary,GetProcAddress,FreeLibrary)

    动态载入(显式链接) DLL方式是指在编译之前并不知道将会调用哪些 DLL 函数, 完全是在运行过程中根据需要决定应调用哪些函数。

     

    使用方法是:用LoadLibrary 函数加载动态链接库到内存,用GetProcAddress函数动态获得 DLL 函数的入口地址。当一个 DLL 文件用LoadLibrary 显式加载后,在任何时刻均可以通过调用FreeLibrary 函数显式地从内存中把它给卸载。

     

    动态调用使用的Windows API 函数主要有 3 个, 分别是LoadLibrary、GetProcAddress 和FreeLibrary。

     

    (1)LoadLibrary函数

     

    注:Delphi中还提供了SafeLoadLibrary 函数,它封装了Loadlibrary 函数,可以装载由Filename 参数指定的WindowsDLL或Linux 共享对象。它简化了DLL的装载并且使装载更加安全。

     

    [格式]:

     

    functionLoadLibrary(LibFileName : PChar): Thandle;

     

    [功能]:加载由参数LibFileName 指定的 DLL 文件。

     

    [说明]:参数LibFileName 指定了要装载的 DLL 文件名,如果LibFileName 没有包含一个路径,系统将按照:当前目录、Windows目录、Windows系统目录、包含当前任务可执行文件的目录、列在 PATH环境变量中的目录等顺序查找文件。

     

    如果函数操作成功,将返回装载 DLL 库模块的实例句柄,否则,将返回一个错误代码,错误代码的定义如下表所示。

     

    错误代码

      含义

      0

      系统内存不够,可执行文件被破坏或调用非法

      2

      文件没有被发现

      3

      路径没有被发现

      5

      企图动态链接一个任务错误或者有一个共享或网络保护错误

      6

      库需要为每个任务建立分离的数据段  

      8

      没有足够的内存启动应用程序  

    10

      Windows  版本不正确  

      11

      可执行文件非法或不是Windows  应用程序,或在.  EXE映像中有错误  

      12

      应用程序为一个不同的操作系统设计(如  OS/2  

      13

      应用程序为  MS  DOS   4. 0  设计  

      14

      可执行文件的类型不知道  

      15

      试图装载一个实模式应用程序(为早期Windows  版本设计)

      16

      试图装载包含可写的多个数据段的可执行文件的第二个实例  

      19

      试图装载一个压缩的可执行文件(文件必须被解压后才能被装载)  

      20

      DLL  文件非法

      21

      应用程序需要  32  位扩展

     

     

    假如在应用程序中用 LoadLibrary 函数装入某一个 DLL 前,其他应用程序已把该 DLL 装入内存中了,则系统将不再装入该 DLL 的另一个实例,而是使该 DLL 引用计数 1 

     

    2GetProcAddress 函数

    [格式]

    function GetProcAddress(Module:Thandle;ProcName:PChar): TfarProc;

     

    [功能]:返回参数 Module 指定的模块中,由参数 ProcName 指定的过程或函数的入口地址。

     

    [说明]:参数 Module 包含被调用函数的 DLL 句柄,这个值由 LoadLibrary 返回, ProcName是指向含有函数名的以 nil 结尾的字符串指针,或者可以是函数的次序值,但大多数情况下,用函数名是一种更稳妥的选择。如果该函数执行成功,则返回 DLL 中由参数 ProcName 指定的过程或函数的入口地址,否则返回 nil 

     

    3FreeLibrary 函数

    [格式]:

    procedure  FreeLibrary(Module: Thandle);

     

    [说明]:将由参数Module 指定的 DLL 文件从内存中卸载 1 次。

     

    [说明]:Module为 DLL 库的句柄。这个值由LoadLibrary 返回。由于 DLL 在内存中只装载一次,因此调用FreeLibrary 首先使 DLL 的引用计数减 1,如果计数减为 0 则卸载该 DLL。

     

    [注意]:每调用一次LoadLibrary 函数就应调用一次FreeLibrary 函数,以保证不会有多余的库模块在应用程序结束后仍留在内存中,否则导致内存泄漏

     

    展开全文
  • 动态链接库 百科名片   动态链接库文件 动态链接库英文为DLL,是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。动态链接提供了一种方法...

    动态链接库

    百科名片

    动态链接库文件 
    动态链接库文件

    动态链接库英文为DLL,是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个DLL 副本的内容。DLL 是一个包含可由多个程序同时使用的代码和数据的库。

    简介

    动态链接库可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。例如,您有一个大型网络游戏,如果把整个数百MB甚至数GB的游戏的代码都放在一个应用程序里,日
    动态链接库

     动态链接库

    后的修改工作将会十分费时,而如果把不同功能的代码分别放在数个动态链接库(DLL)中,您无需重新生成或安装整个程序就可以应用更新。
    下表说明了 Windows 操作系统中的一些作为 DLL 实现的文件:

    · ActiveX控件(.ocx) 文件

    ActiveX 控件的一个示例是日历控件,它使您可以从日历中选择日期。

    · 控制面板(.cpl) 文件

    .cpl 文件的一个示例是位于控制面板中的项。每个项都是一个专用 DLL。

    · 设备驱动程序(.drv) 文件

    设备驱动程序的一个示例是控制打印到打印机打印机驱动程序

    动态链接库文件

    动态链接库文件,是一种不可执行的二进制程序文件,它允许程序共享执行特殊任务所必需的代码和其他资源。Windows提供的DLL文件中包含了允许基于Windows的程序在Windows环境下操作的许多函数和资源。一般被存放在C:\Windows\System目录下。Windows中,DLL多数情况下是带有DLL扩展名的文件,但也可能是EXE或其他扩展名;Debian系统中常常是.so的文件。它们向运行于Windows操作系统下的程序提供代码、数据或函数。程序可根据DLL文件中的指令打开、启用、查询、禁用和关闭驱动程序

    DLL 优点

    1、扩展了应用程序的特性;
    2、可以用许多种编程语言来编写;
    3、简化了软件项目的管理;
    4、有助于节省内存
    5、有助于资源共享
    6、有助于应用程序的本地化;
    7、有助于解决平台差异;
    8、可以用于一些特殊的目的。windows使得某些特性只能为DLL所用。

    DLL文件损坏

    当前木马病毒经常感染或者替换系统文件dll文件,部分安全
    dll图标

     dll图标

    工具查杀后并未对dll文件进行系统修复,所以经常会出现以下现象: 
    1、网络游戏无法打开
    2、电脑没声音
    4、桌面无法显示
    5、主页被修改为网址导航 
    6、桌面图标无法删除(淘宝、小游戏、电影等等,重启同样不能正常删除)

    DLL 依赖项

    当某个程序或 DLL 使用其他 DLL 中的 DLL 函数时,就会创建依赖项。因此,该程序就不再是独立的,并且如果该依赖项被损坏,该程序就可能遇到问题。例如,如果发生下列操作之一,则该程序可能无法运行:
    · 依赖 DLL 升级到新版本。
    · 修复了依赖 DLL。
    · 依赖 DLL 被其早期版本覆盖。
    · 从计算机中删除了依赖 DLL。
    这些操作通常称为 DLL 冲突。如果没有强制实现向后兼容性,则该程序可能无法成功运行。

    DLL 入口点

    在创建 DLL 时,可以有选择地指定入口点函数。当进程或线程将它们自身附加到 DLL 或者将它们自身从 DLL 分离时,将调用入口点函数。您可以使用入口点函数根据 DLL 的需要来初始化数据结构或者销毁数据结构。此外,如果应用程序多线程的,则可以在入口点函数中使用线程本地存储 (TLS) 来分配各个线程专用的内存。下面的代码是一个 DLL 入口点函数的示例:
    BOOL APIENTRY DllMain(
    HANDLE hModule, // DLL模块的句柄
    DWORD ul_reason_for_call, // 调用本函数的原因
    LPVOID lpReserved ) // 保留
    {
    switch ( ul_reason_for_call )
    {
    case DLL_PROCESS_ATTACH:
    //进程正在加载本DLL
    break;
    case DLL_THREAD_ATTACH:
    //一个线程被创建
    break;
    case DLL_THREAD_DETACH:
    //一个线程正常退出
    break;
    case DLL_PROCESS_DETACH:
    //进程正在卸载本DLL
    break;
    }
    return TRUE;
    //返回TRUE,表示成功执行本函数
    }
    入口点函数返回 FALSE 值时,如果您使用的是加载时动态链接,则应用程序不启动。如果您使用的是运行时动态链接,则只有个别 DLL 不会加载。
    入口点函数只应执行简单的初始化任务,不应调用任何其他 DLL 加载函数或终止函数。例如,在入口点函数中,不应直接或间接调用 LoadLibrary 函数或 LoadLibraryEx 函数。此外,不应在进程终止时调用 FreeLibrary 函数。
    注意:在多线程应用程序中,请确保将对 DLL 全局数据的访问进行同步(线程安全),以避免可能的数据损坏。为此,请使用 TLS 为各个线程提供唯一的数据。

    导出 DLL 函数

    要导出 DLL 函数,您可以向导出的 DLL 函数中添加函数关键字,也可以创建模块定义文件(.def) 以列出导出的 DLL 函数。

    两种方法

    方法一、向导出的 DLL 函数中添加函数关键字
    要使用函数关键字,您必须使用以下关键字来声明要导出的各个函数:
    __declspec(dllexport)
    要在应用程序中使用导出的 DLL 函数,您必须使用以下关键字来声明要导入的各个函数:
    __declspec(dllimport)
    通常情况下,您最好使用一个包含 define 语句和 ifdef 语句的头文件,以便分隔导出语句和导入语句。
    方法二、创建模块定义文件 (.def) 以列出导出的 DLL 函数
    使用模块定义文件来声明导出的 DLL 函数。当您使用模块定义文件时,您不必向导出的 DLL 函数中添加函数关键字。在模块定义文件中,您可以声明 DLL 的 LIBRARY 语句和 EXPORTS 语句。

    特别调用

    关于特定情况下的调用,比如DLL函数中使用到了win32 API或者将C++生成的DLL供标准C语言使用,则需要注意以下一些情况:
    如果使用到了win32 API,则应该使用调用方式为“__stdcall”。
    在将C++生成的DLL供标准C语言使用,输出文件需要用“extern "C"”修饰,否则不能被标准C语言调用。如果使用“__stdcall”调用方式,可能产生C不识别的修饰名,所以设置导出函数时要采用.def文件形式,而不是__declspec(dllexport)形式。后者会进行修饰名转换,C语言无法识别函数。
    下面的代码是一个定义文件的示例。
    // SampleDLL.def
    //
    LIBRARY "sampleDLL"
    EXPORTS
    HelloWorld示例 DLL 和应用程序XXXXXXXX 在 MicrosoftVisual C++6.0 中,可以通过选择“Win32动态链接库”项目类型或“MFC应用程序向导 (dll)”来创建 DLL。下面的代码是一个在 Visual C++ 中通过使用“Win32 动态链接库”项目类型创建的 DLL 的示例。
    // SampleDLL.cpp
    //#include "stdafx.h"
    #define EXPORTING_DLL
    #include "sampleDLL.h"
    BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
    {
    return TRUE;
    }
    void HelloWorld(){
    MessageBox( NULL, TEXT("Hello World"), TEXT("In a DLL"), MB_OK);
    }
    // File: SampleDLL.h
    //#ifndef INDLL_H
    #define INDLL_H
    #ifdef EXPORTING_DLLextern __declspec(dllexport) void HelloWorld() ;
    #elseextern __declspec(dllimport) void HelloWorld() ;
    #endif
    #endif
    下面的代码是一个“Win32应用程序”项目的示例,该示例调用 SampleDLL DLL 中的导出 DLL 函数。
    // SampleApp.cpp
    //#include "stdafx.h"
    #include "sampleDLL.h"
    int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
    {
    HelloWorld();
    return 0;
    }
    注意:在加载时动态链接中,您必须链接在生成 SampleDLL 项目时创建的 SampleDLL.lib导入库
    在运行时动态链接中,您应使用与以下代码类似的代码来调用 SampleDLL.dll 导出 DLL 函数。
    ...
    typedef VOID (*DLLPROC) (LPTSTR);
    ...
    HINSTANCE hinstDLL;
    DLLPROC HelloWorld;
    BOOL fFreeDLL;
    hinstDLL = LoadLibrary("sampleDLL.dll");
    if (hinstDLL != NULL)
    {
    HelloWorld = (DLLPROC) GetProcAddress(hinstDLL, "HelloWorld");
    if (HelloWorld != NULL)
    (HelloWorld);
    fFreeDLL = FreeLibrary(hinstDLL);
    }
    ...

    DLL内容说明

    KERNEL32.DLL ---- 低级内核函数。使用他可以完成内存管理、任务管理
    资源控制等。
    USER32.DLL------与windows管理有关的函数。消息、菜单光标计时器
    、通信和其他大多数非现实函数都可以从这里找到
    GDI32.DLL-------图形设备接口库。与设备输出有关的函数:大多数绘图
    、显示场景、图元文件、坐标及其字体函数都可以从这里找到。
    COMDLG32.DLL\LZ32.DLL\VERSION.DLL\---这都是提供一些附加函数的库,包
    括通用对话框、文件压缩版本控制的支持。
    COMCTL32.DLL --------一个新的windows控件集合,比如TreeView和RichTextBox
    等等,最初这个是为了win95而制作的,但是现在也使用与NT下
    MAPI32.DLL---------提供了一套电子邮件的专用函数
    NETAPI32.DLL--------提供了一套访问和控制网络的函数
    ODBC32.DLL--------ODBC功能的DLL之DLL(Delay Locked Loop,延时锁定回路提供一个数据滤波信号)

    DLL错误的危害

    系统文件auditpolicygpinterop.dll出错,是由于木马病毒、或不小心下载了流氓软件被感染所致。而该文件又是系统/程序正常运行的前提条件,所以一旦不幸被感染,通常会伴随下几种情况
    1、桌面图标无法删除(淘宝、小游戏、电影等等,重启同样不能正常删除)
    2、网络游戏打不开(DNF,穿越火线,魔兽世界等等)
    3、电脑无故蓝屏
    4、电脑没声音
    5、桌面无法显示
    6、一些程序无法正常使用(比如双击无响应等一系列情况

    DLL修复方法

    部分.dll缺失可以从其他电脑或者网上上下载拷贝到,c盘windows目录下来完成修复。
    auditpolicygpinterop.dll出错,很多是因为中了流氓软件的招,如果不太了解系统,不知道应该把auditpolicygpinterop.dll放在哪,那么建议使用修复工具对系统进行最全面的扫描和修复。

    dll木马原理

    DLL是编译好的代码,与一般程序没什么大差别,只是它不能独立运行,需要程序调用。那么,DLL与木马能扯上什么关系呢?如果你学过编程并且写过DLL,就会发现,其实DLL的代码和其他程序几乎没什么两样,仅仅是接口和启动模式不同,只要改动一下代码入口,DLL就变成一个独立的程序了。当然,DLL文件是没有程序逻辑的,这里并不是说DLL=EXE,不过,依然可以把DLL看做缺少了main入口的EXE,DLL带的各个功能函数可以看作一个程序的几个函数模块。DLL木马就是把一个实现了木马功能的代码,加上一些特殊代码写成DLL文件,导出相关的API,在别人看来,这只是一个普通的DLL,但是这个DLL却携带了完整的木马功能,这就是DLL木马的概念。也许有人会问,既然同样的代码就可以实现木马功能,那么直接做程序就可以,为什么还要多此一举写成DLL呢?这是为了隐藏,因为DLL运行时是直接挂在调用它的程序的进程里的,并不会另外产生进程,所以相对于传统EXE木马来说,它很难被查到。

    DLL Hell

    动态链接库(DLL)地狱——当使用COM组件的应用程序被安装在一台机器上,在安装过程中会更新注册表的COM组件信息。因此,有这些DLL时,将被覆盖一些其他的应用程序在同一台计算机上安装了一个机会。因此,应用程序,指的是一个特定的DLL错误的DLL。这造成了重大的问题,当一个应用程序指的是一个特定版本的DLL。[1]
    展开全文
  • 静态链接库与动态链接

    千次阅读 2014-05-31 22:37:47
    静态链接库与动态链接库 静态链接库(static link library),也就是你经常看到的*.lib文件;动态链接库(Dynamic Link Library),也就是你经常看到的*.dll文件。如果你是初学者或者对静态库与动态库还没有概念,...

    静态链接库与动态链接库

    静态链接库(static link library),也就是你经常看到的*.lib文件;动态链接库(Dynamic Link Library),也就是你经常看到的*.dll文件。如果你是初学者或者对静态库与动态库还没有概念,可以先将其理解为一种仓库,它提供给你一些可以直接拿来用的变量、函数或类,在仓库的发展历史中,经历了“无库-->静态库-->动态库”的过程。

    静态库与动态库的区别

    1.静态(lib)将导出声明和实现都放在lib中。编译(lib)文件中用到的所有函数代码直接链接进目标程序(exe文件)动态(dll)相当于一个h文件,是对实现部分(.dll文件)的导出部分的声明。编译后只是将导出声明部分编译到宿主程序中,运行时候需要相应的dll文件支持

    2.静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。

    3.使用静态库时要同时包含.lib.h文件。

    静态链接库和动态链接库

    关于动态库的更详细介绍,已经有高人总结的很详细了,我就不班门弄斧了。

    请看以下学习资料:《VC++动态链接库(dll)编程深入浅出

    展开全文
  • 库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。例如:libhello.so libhello.a 为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: libhello.so.1.0,由于程序连接默认以.so为...

    库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。例如:libhello.so libhello.a
    为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: libhello.so.1.0,由于程序连接默认以.so为文件后缀名。所以为了使用这些库,通常使用建立符号连接的方式。
    ln -s libhello.so.1.0 libhello.so.1
    ln -s libhello.so.1 libhello.so
    使用库
    当 要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。然 而,对动态库而言,就不是这样。动态库会在执行程序内留下一个标记‘指明当程序执行时,首先必须载入这个库。由于动态库节省空间,linux下进行连接的 缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。
    现在假设有一个叫hello的程序开发包,它提供一个静态库libhello.a 一个动态库libhello.so,一个头文件hello.h,头文件中提供sayhello()这个函数
    /* hello.h */
    void sayhello();
    另外还有一些说明文档。这一个典型的程序开发包结构
    1.与动态库连接
    linux默认的就是与动态库连接,下面这段程序testlib.c使用hello库中的sayhello()函数
    /*testlib.c*/
    #include  
    #include  
    int main()
    {
    sayhello();
    return 0;
    }
    使用如下命令进行编译
    $gcc -c testlib.c -o testlib.o
    用如下命令连接:
    $gcc testlib.o -lhello -o testlib
    在连接时要注意,假设libhello.o 和libhello.a都在缺省的库搜索路径下/usr/lib下,如果在其它位置要加上-L参数
    与与静态库连接麻烦一些,主要是参数问题。还是上面的例子:
    $gcc testlib.o -o testlib -WI,-Bstatic -lhello
    注:这个特别的"-WI,-Bstatic"参数,实际上是传给了连接器ld.
    指示它与静态库连接,如果系统中只有静态库当然就不需要这个参数了。
    如果要和多个库相连接,而每个库的连接方式不一样,比如上面的程序既要和libhello进行静态连接,又要和libbye进行动态连接,其命令应为:
    $gcc testlib.o -o testlib -WI,-Bstatic -lhello -WI,-Bdynamic -lbye
    3.动态库的路径问题
    为了让执行程序顺利找到动态库,有三种方法:
    (1)把库拷贝到/usr/lib和/lib目录下。
    (2)在LD_LIBRARY_PATH环境变量中加上库所在路径。例如动态库libhello.so在/home/ting/lib目录下,以bash为例,使用命令:
    $export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ting/lib
    (3) 修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新。这样,加入的目录下的所有库文件都可见、
    4.查看库中的符号
    有 时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有符号。库既可以是静态的也可以是动态的。nm列出的符号有很多,常见的有 三种,一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;一种是库中定义的函数,用T表示,这是最常见的;另外一种是所谓的“弱 态”符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。例如,假设开发者希望知道上央提到的hello库中是否定义了 printf():
    $nm libhello.so |grep printf
    U printf
    U表示符号printf被引用,但是并没有在函数内定义,由此可以推断,要正常使用hello库,必须有其它库支持,再使用ldd命令查看hello依赖于哪些库:
    $ldd hello
    libc.so.6=>/lib/libc.so.6(0x400la000)
    /lib/ld-linux.so.2=>/lib/ld-linux.so.2 (0x40000000)
    从上面的结果可以继续查看printf最终在哪里被定义,有兴趣可以go on
    生成库
    第一步要把源代码编绎成目标代码。以下面的代码为例,生成上面用到的hello库:

    /* hello.c */
    #include  
    void sayhello()
    {
    printf("hello,world/n");
    }
    用gcc编绎该文件,在编绎时可以使用任何全法的编绎参数,例如-g加入调试代码等:
    gcc -c hello.c -o hello.o
    1.连接成静态库
    连接成静态库使用ar命令,其实ar是archive的意思
    $ar cqs libhello.a hello.o
    2.连接成动态库
    生成动态库用gcc来完成,由于可能存在多个版本,因此通常指定版本号:
    $gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o
    另外再建立两个符号连接:
    $ln -s libhello.so.1.0 libhello.so.1
    $ln -s libhello.so.1 libhello.so
    这样一个libhello的动态连接库就生成了。最重要的是传gcc -shared 参数使其生成是动态库而不是普通执行程序。
    -Wl 表示后面的参数也就是-soname,libhello.so.1直接传给连接器ld进行处理。实际上,每一个库都有一个soname,当连接器发现它正 在查找的程序库中有这样一个名称,连接器便会将soname嵌入连结中的二进制文件内,而不是它正在运行的实际文件名,在程序执行期间,程序会查找拥有 soname名字的文件,而不是库的文件名,换句话说,soname是库的区分标志。
    这样做的目的主要是允许系统中多个版本的库文件共存,习惯上在命名库文件的时候通常与soname相同
    libxxxx.so.major.minor
    其中,xxxx是库的名字,major是主版本号,minor 是次版本号



    =====================

    摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库可以有效的减少程序大小,节省空间,提 高效率,增加程序的可扩展性,便于模块化管理。但不同操作系统的动态库由于格式 不同,在需要不同操作系统调用时需要进行动态库程序移植。本文分析和比较了两种操作系统动态库技术,并给出了将Visual C++编制的动态库移植到Linux上的方法和经验。
      
      1、引言
      
      动态库(Dynamic Link Library abbr,DLL)技术是程序设计中经常采用的技术。其目的减少程序的大小,节省空间,提高效率,具有很高的灵活性。采用动态库技术对于升级软件版本更加 容易。与静态库(Static Link Library)不同,动态库里面的函数不是执行程序本身的一部分,而是根据执行需要按需载入,其执行代码可以同时在多个程序中共享。
      
      在Windows和Linux操作系统中,都可采用这种方式进行软件设计,但他们的调用方式以及程序编制方式不尽相同。本文首先分析了在这两种操作系 统中通常采用的动态库调用方法以及程序编制方式,然后分析比较了这两种方式的不同之处,最后根据实际移植程序经验,介绍了将VC++编制的Windows 动态库移植到Linux下的方法。
      
      2、动态库技术
      
      2.1 Windows动态库技术
      
      动态链接库是实现Windows应用程序共享资源、节省内存空间、提高使用效率的一个重要技术手段。常见的动态库包含外部函数和资源,也有一些动态库 只包含资源,如Windows字体资源文件,称之为资源动态链接库。通常动态库以.dll,.drv、.fon等作为后缀。相应的windows静态库通 常以.lib结尾,Windows自己就将一些主要的系统功能以动态库模块的形式实现。
      
      Windows动态库在运行时被系统加载到进程的虚拟空间中,使用从调用进程的虚拟地址空间分配的内存,成为调用进程的一部分。DLL也只能被该进程 的线程所访问。DLL的句柄可以被调用进程使用;调用进程的句柄可以被DLL使用。DLL模块中包含各种导出函数,用于向外界提供服务。DLL可以有自己 的数据段,但没有自己的堆栈,使用与调用它的应用程序相同的堆栈模式;一个DLL在内存中只有一个实例;DLL实现了代码封装性;DLL的编制与具体的编 程语言及编译器无关,可以通过DLL来实现混合语言编程。DLL函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。
      
      根据调用方式的不同,对动态库的调用可分为静态调用方式和动态调用方式。
      
      (1)静态调用,也称为隐式调用,由编译系统完成对DLL的加载和应用程序结束时DLL卸载的编码(Windows系统负责对DLL调用次数的计 数),调用方式简单,能够满足通常的要求。通常采用的调用方式是把产生动态连接库时产生的.LIB文件加入到应用程序的工程中,想使用DLL中的函数时, 只须在源文件中声明一下。 LIB文件包含了每一个DLL导出函数的符号名和可选择的标识号以及DLL文件名,不含有实际的代码。Lib文件包含的信息进入到生成的应用程序中,被调 用的DLL文件会在应用程序加载时同时加载在到内存中。
      
      (2)动态调用,即显式调用方式,是由编程者用API函数加载和卸载DLL来达到调用DLL的目的,比较复杂,但能更加有效地使用内存,是编制大型应用程序时的重要方式。在Windows系统中,与动态库调用有关的函数包括:
      
      ①LoadLibrary(或MFC 的AfxLoadLibrary),装载动态库。
      ②GetProcAddress,获取要引入的函数,将符号名或标识号转换为DLL内部地址。
      ③FreeLibrary(或MFC的AfxFreeLibrary),释放动态链接库。
      
      在windows中创建动态库也非常方便和简单。在Visual C++中,可以创建不用MFC而直接用C语言写的DLL程序,也可以创建基于MFC类库的DLL程序。每一个DLL必须有一个入口点,在VC++ 中,DllMain是一个缺省的入口函数。DllMain负责初始化(Initialization)和结束(Termination)工作。动态库输出 函数也有两种约定,分别是基于调用约定和名字修饰约定。DLL程序定义的函数分为内部函数和导出函数,动态库导出的函数供其它程序模块调用。通常可以有下 面几种方法导出函数:
      
      ①采用模块定义文件的EXPORT部分指定要输入的函数或者变量。
      ②使用MFC提供的修饰符号_declspec(dllexport)。
      ③以命令行方式,采用/EXPORT命令行输出有关函数。
      
      在windows动态库中,有时需要编写模块定义文件(.DEF),它是用于描述DLL属性的模块语句组成的文本文件。
      
      2.2 Linux共享对象技术
      
      在Linux操作系统中,采用了很多共享对象技术(Shared Object),虽然它和Windows里的动态库相对应,但它并不称为动态库。相应的共享对象文件以.so作为后缀,为了方便,在本文中,对该概念不进 行专门区分。Linux系统的/lib以及标准图形界面的/usr/X11R6/lib等目录里面,就有许多以so结尾的共享对象。同样,在Linux 下,也有静态函数库这种调用方式,相应的后缀以.a结束。Linux采用该共享对象技术以方便程序间共享,节省程序占有空间,增加程序的可扩展性和灵活 性。Linux还可以通过LD-PRELOAD变量让开发人员可以使用自己的程序库中的模块来替换系统模块。
      
      同Windows系统一样,在Linux中创建和使用动态库是比较容易的事情,在编译函数库源程序时加上-shared选项即可,这样所生成的执行程 序就是动态链接库。通常这样的程序以so为后缀,在Linux动态库程序设计过程中,通常流程是编写用户的接口文件,通常是.h文件,编写实际的函数文 件,以.c或.cpp为后缀,再编写makefile文件。对于较小的动态库程序可以不用如此,但这样设计使程序更加合理。
      
      编译生成动态连接库后,进而可以在程序中进行调用。在Linux中,可以采用多种调用方式,同Windows的系统目录(../system32等) 一样,可以将动态库文件拷贝到/lib目录或者在/lib目录里面建立符号连接,以便所有用户使用。下面介绍Linux调用动态库经常使用的函数,但在使 用动态库时,源程序必须包含dlfcn.h头文件,该文件定义调用动态链接库的函数的原型。
      
      (1)_打开动态链接库:dlopen,函数原型void *dlopen (const char *filename, int flag);
      dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄。
      
      (2)取函数执行地址:dlsym,函数原型为: void *dlsym(void *handle, char *symbol);
      dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。
      
      (3)关闭动态链接库:dlclose,函数原型为: int dlclose (void *handle);
      dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
      
      (4)动态库错误函数:dlerror,函数原型为: const char *dlerror(void); 当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。
      
      在取到函数执行地址后,就可以在动态库的使用程序里面根据动态库提供的函数接口声明调用动态库里面的函数。在编写调用动态库的程序的makefile文件时,需要加入编译选项-rdynamic和-ldl。
      
      除了采用这种方式编写和调用动态库之外,Linux操作系统也提供了一种更为方便的动态库调用方式,也方便了其它程序调用,这种方式与Windows 系统的隐式链接类似。其动态库命名方式为“lib*.so.*”。在这个命名方式中,第一个*表示动态链接库的库名,第二个*通常表示该动态库的版本号, 也可以没有版本号。在这种调用方式中,需要维护动态链接库的配置文件/etc/ld.so.conf来让动态链接库为系统所使用,通常将动态链接库所在目 录名追加到动态链接库配置文件中。如具有X window窗口系统发行版该文件中都具有/usr/X11R6/lib,它指向X window窗口系统的动态链接库所在目录。为了使动态链接库能为系统所共享,还需运行动态链接库的管理命令./sbin/ldconfig。在编译所引 用的动态库时,可以在gcc采用 ?l或-L选项或直接引用所需的动态链接库方式进行编译。在Linux里面,可以采用ldd命令来检查程序依赖共享库。
      
      3、两种系统动态库比较分析
      
      Windows和Linux采用动态链接库技术目的是基本一致的,但由于操作系统的不同,他们在许多方面还是不尽相同,下面从以下几个方面进行阐述。
      
      (1)动态库程序编写,在Windows系统下的执行文件格式是PE格式,动态库需要一个DllMain函数作为初始化的人口,通常在导出函数的声明 时需要有_declspec(dllexport)关键字。Linux下的gcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要到函数做特 别声明,编写比较方便。
      
      (2)动态库编译,在windows系统下面,有方便的调试编译环境,通常不用自己去编写makefile文件,但在linux下面,需要自己动手去编写makefile文件,因此,必须掌握一定的makefile编写技巧,另外,通常Linux编译规则相对严格。
      
      (3)动态库调用方面,Windows和Linux对其下编制的动态库都可以采用显式调用或隐式调用,但具体的调用方式也不尽相同。
      
      (4)动态库输出函数查看,在Windows中,有许多工具和软件可以进行查看DLL中所输出的函数,例如命令行方式的dumpbin以及VC++工 具中的DEPENDS程序。在Linux系统中通常采用nm来查看输出函数,也可以使用ldd查看程序隐式链接的共享对象文件。
      
      (5)对操作系统的依赖,这两种动态库运行依赖于各自的操作系统,不能跨平台使用。因此,对于实现相同功能的动态库,必须为两种不同的操作系统提供不同的动态库版本。
      
      4、动态库移植方法
      
      如果要编制在两个系统中都能使用的动态链接库,通常会先选择在Windows的VC++提供的调试环境中完成初始的开发,毕

    展开全文
  • 深入浅出静态链接和动态链接

    万次阅读 多人点赞 2018-05-06 09:24:48
    作为一名C/C++程序员,对于编译链接的过程要了然于胸。首先大概介绍一下,编译分为3步,首先对源文件进行预处理,这个过程主要是处理一些#号定义的命令或语句(如宏、#include、预编译指令#ifdef等),生成*.i文件;...
  • 理解动态链接

    千次阅读 2018-06-04 11:27:12
    今天我将从以下三个方面来记录一下我对动态链接的学习理解。1.共享库的作用和生成方法2.加载和链接共享库的方法3.用到的相关技术--延迟绑定首先我们先来看一下共享库的定义:共享库是致力于解决静态库缺陷的一个现代...
  • 首先DLL大家应该都知道,动态链接库(Dynamic Link Library 或者 Dynamic-link Library,缩写为 DLL),不知道的网上搜一下,稍微开发过Windows程序的小白都应该比较清楚,具体的概念不是本文的重点。 动态链接 是...
  • 1. 链接、静态链接和动态链接概念 程序设计追求的是模块化,一个复杂软件由许多模块组成,通常将每个模块进行单独编译,然后将它们组装起来,组装的过程就是链接。链接处理的是把各个模块之间相互应用的部分都...
  • 什么是链接? 对于初学C语言的朋友,可能对链接...静态、动态链接? 1、什么是静态链接? 静态链接是由链接器在链接时将库的内容加入到可执行程序中的做法。链接器是一个独立程序,将一个或多个库或目标文件(先前由...
  • 动态链接库知识点归纳之一(DLL概念,如何建立,如何使用,如何优化,如何查看
  • C++ 动态链接库和静态链接库

    千次阅读 2019-09-23 15:59:58
      今天对C++生成动态链接路和静态链接库非常感兴趣,必须搞定,否则都没有心情干其他事了。Let’s go~ 文章目录源程序编译链接生成文件格式预编译编译和优化编译优化生成目标文件链接什么是库?动态静态的区别...
  • 静态链接与动态链接的区别

    千次阅读 2015-10-09 17:38:23
    链接可以分为静态链接与动态链接,下文将分别讲解这两种方式的特点与其区别。 静态链接 特点:在生成可执行文件的时候(链接阶段),把所有需要的函数的二进制代码都包含到可执行文件中去。因此,链接器需要知道...
  • 静态链接库、动态链接库使用方法

    千次阅读 2017-08-27 20:18:44
    总结一下动态链接库和静态链接库。
  • 动态链接

    千次阅读 2006-10-12 20:24:00
    Windows运作机制的核心是一个称作「动态链接」的概念。Windows提供了应用程序丰富的可呼叫函数,大多数用于实作其使用者接口和在视讯显示器上显示文字和图形。这些函数采用动态链接库(Dynamic Linking Library,DLL...
  • 动态链接库和静态链接库的基本概念请参考 1.《深入理解计算机系统》第七章链接 2.《程序员的自我修养》第4章 静态链接和第7章 动态链接 3.http://blog.jobbole.com/86852/ 目的 为了封装代码,简化接口,...
  • 程序的静态链接,动态链接和装载

    千次阅读 2017-04-14 09:59:07
    转自:程序的静态链接,动态链接和装载 参考自:http://www.xuebuyuan.com/1730287.html 一、程序编译链接的整体流程 二、目标文件的样子(以linux下的elf文件格式为例) 三、静态链接 四、装载 五、...
  • 使用动态链接

    千次阅读 2013-08-20 11:22:27
    1. 动态链接库是程序运行时加载的库,当动态链接库正确安装后,所有的程序都可以使用动态库来运行程序。动态链接库是目标文件的集合,目标文件在动态链接库中的组织方式是按照特殊方式形成的。库中函数和变量的地址...
  • 关于动态链接与静态链接

    万次阅读 2012-03-22 14:48:31
    大家都知道应用程序有两种链接方式,一种是静态链接,一种是动态链接,这两种链接方式各有好处。 程序的静态连接还是动态连接是根据编译器的连接参数指定的。 所谓静态链接就是在编译链接时直接将需要的执行代码...
  • 一、引言在上一篇博客里,我主要实现了使用 C++ 自行编写和静态调用动态链接库的功能。这里附上上一篇博客的地址: 简单 Demo:C++编写、调用动态链接动态链接库除了可以静态调用外,还可以动态调用。可能这里对...
  • 动态链接库DLL

    千次阅读 2016-05-08 23:20:17
    动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多...
  • JVM-虚拟机栈之动态链接

    万次阅读 2019-07-16 19:48:09
    *****标题写的是介绍虚拟机栈中的动态链接,但是这里讲解的是动态链接和静态链接的区别***** 一.概述: Class文件的常量池中存在有大量的符号引用,字节码中的方法调用指令就以指向常量池的引用作为参数 部分符号...
  • 静态库,动态库,静态链接和动态链接这几个概念理解起来很简单,本文主要是收集了网上的一些观点作了一个较全面的总结。 一、问题 1,静态库是什么? 2,动态库是什么? 3,两者的区别? 4,静态链接? 5...
  • 2 动态链接库编程之基础概念 DLL(Dynamic Linkable Library)的概念 你可以简单的把DLL看成一种仓库,它提供你一些可以直接拿来用的变量、函数或类。在仓库的发展史上经历了“无库 -- 静态链接库 -- 动态链接库”...
  • 动态链接和静态链接的区别

    千次阅读 2018-12-16 21:16:44
    动态链接和静态链接的区别 动态链接和静态链接的区别 https://www.cnblogs.com/njczy2010/p/5793477.html 一、分别编译与链接(Linking) 大多数高级语言都支持分别编译,程序员可以显式地把程序划分为独立的...
  • Windows和Linux动态链接库总结

    千次阅读 2014-08-12 22:28:27
    动态链接库为模块化应用...(1)动态链接库的概念 动态链接库是应用程序的一个模块,这个模块用于导出一些函数和数据供程序中的其他模 块使用。应该从以下 3 个方面来理解这个概念动态链接库是应用程序的一部分
  • 编译器链接过程 静态链接 动态链接

    千次阅读 2015-11-01 16:58:14
    理解链接有很多好处: 有助于构造大型程序 有助于避免一些危险编程错误 有助于理解其他重要的系统概念 让你能够利用共享库 1. 编译器驱动程序 编译命令,假设有main.c和swap.c两个源文件 [cpp]view ...
  • 博客转载自:Linux-动态链接与静态链接对比 一、库的基础概念: 在windows平台和linux平台下都大量存在着库。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。由于windows和linux的本质不同...
  • 动态链接

    千次阅读 2008-04-07 23:07:00
    一、动态链接库的概念 动态链接库(Dynamic Link Library,缩写为DLL)是一个可以被其它应用程序共享的程序模块,其中封装了一些可以被共享的例程和资源。动态链接库文件的扩展名一般是dll,也有可能是drv、sys和fon...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 196,474
精华内容 78,589
关键字:

动态链接的概念