动态链接库及静态链接库(windows下的.dll.lib和linux下的.so.a)

更新时间:2023-04-08 08:47:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

动态链接库及静态链接库(Windows 下的.dll .Iib 和IinuX下的.so .a )

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*/

#i nclude

#i nclude

int mai n()

{

Sayhello();

return 0;

}

使用如下命令进行编译

$gcc -C testlib.c -o testlib.o

用如下命令连接:

$gcc testlib.o -lhello -o testlib

在连接时要注意,假设libhello.o和libhello.a都在缺省的库搜索路径下/usr/lib下,如果在

动态链接库及静态链接库(Windows 下的.dll .Iib 和IinuX下的.so .a )

3.动态库的路径问题

为了让执行程序顺利找到动态库,有三种方法:

(1) 把库拷贝到∕usr∕lib和/Iib目录下。

⑵在 LD_LIBRARY_PATH 环境变量中加上库所在路径。例如动态库IibheIlo.so 在

∕home∕ting/lib目录下,以 bash为例,使用命令:|

$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ti ng/lib

(3)修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新。这样,

加入的目录下的所有库文件都可见、

4.查看库中的符号

有时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有

符号。库既可以是静态的也可以是动态的。nm列出的符号有很多,常见的有三种,一种

是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;一种是库中定义的函数,用T表示,这是最常见的;另外一种是所谓的弱态”符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。例如,假设开发者希望知道上央提

到的hello库中是否定义了 Printf():

$nm libhello.so |grep Printf

/* hello.c */

#i nclude

void Sayhello()

{

Prin tf("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,-s On ame,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

-Wl表示后面的参数也就是-Soname,libhello.so.1 直接传给连接器ld进行处理。实际上,每

-Wl表示后面的参数也就是-Soname,libhello.so.1 直接传给连接器ld进行处理。实际上,每

一个库都有一个 Soname ,当连接器发现它正

在查找的程序库中有这样一个名称,连接器

便会将Soname 嵌入连结中的二进制文件内, 而不是它正在运行的实际文件名, 在程序执行

期间,程序会查找拥有 Soname 名字的文件,而不是库的文件名,换句话说,

Soname 是库 的区分标志。

这样做的目的主要是允许系统中多个版本的库文件共存,

习惯上在命名库文件的时候通常与

摘要:动态链接库技术实现和设计程序常用的技术,在

WindowS 和LinUX 系统中都有动态 库的概念,采用动态库可以有效的减少程序大小,

节省空间,提高效率,增加程序的可扩展 性,便于模块化管理。但不同操作系统的动态库由于格式

不同,在需要不同操作系统调用 时需要进行动态库程序移植。本文分析和比较了两种操作系统动态库技术,并给出了将 ViSUaI C++编

制的动态库移植到 LinUX 上的方法和经验。

动态库(Dynamic Link Library abbr , DLL)技术是程序设计中经常采用的技术。其目 的减少程序的大小, 节省空间,提高效率,具有很高的灵活性。采用动态库技术对于升级软

件版本更加容易。与静态库(StatiC Link Library )不同,动态库里面的函数不是执行程序本 身的一部分,而是根据执行需要按需载入,其执行代码可以同时在多个程序中共享。

在Windows 和LinUX 操作系统中,都可采用这种方式进行软件设计,但他们的调用方 式以及程序编制方式不尽相同。本文首先分析了在这两种操作系统中通常采用的动态库调用 方法以及程序编制方式,然后分析比较了这两种方式的不同之处,

最后根据实际移植程序经 验,介绍了将 VC++编制的Windows 动态库移植到LinUX 下的方法。

2、动态库技术

2.1 Windows 动态库技术

动态链接库是实现 Windows 应用程序共享资源、节省内存空间、提高使用效率的一个 重要技术手段。常见的动态库包含外部函数和资源,也有一些动态库只包含资源,如

Windows 字体资源文件,称之为资源动态链接库。通常动态库以

.dll ,.drv 、.fon 等作为后 缀。相应的 Windows 静态库通常以」ib 结尾,Windows 自己就将一些主要的系统功能以动

态库模块的形式实现。

Win dows 动态库在运行时被系统加载到进程的虚拟空间中,使用从调用进程的虚拟地 址空间分配的内存,成为调用进程的一部分。

DLL 也只能被该进程的线程所访问。 DLL 的句

一个库都有一个Soname ,当连接器发现它正在查找的程序库中有这样一个名称,连接器柄可以被调用进程使用;调用进程的句柄可以被 DLL使用。DLL模块中包含各种导出函数,

用于向外界提供服务。 DLL可以有自己的数据段,但没有自己的堆栈,使用与调用它的应用程序相同的堆栈模式;一个DLL在内存中只有一个实例;DLL实现了代码封装性;DLL的编

制与具体的编程语言及编译器无关,可以通过DLL来实现混合语言编程。DLL函数中的代

码所创建的任何对象(包括变量)都归调用它的线程或进程所有。

根据调用方式的不同,对动态库的调用可分为静态调用方式和动态调用方式。

(1) 静态调用,也称为隐式调用,由编译系统完成对DLL的加载和应用程序结束时DLL 卸载的编码(Windows系统负责对DLL调用次数的计数),调用方式简单,能够满足通常的一要求。通常采用的调用方式是把产生动态连接库时产生的丄IB文件加入到应用程序的工程中,想使用DLL中的函数时,只须在源文件中声明一下。LIB文件包含了每一个 DLL导出函数

的符号名和可选择的标识号以及DLL文件名,不含有实际的代码。Lib文件包含的信息进入

到生成的应用程序中,被调用的DLL文件会在应用程序加载时同时加载在到内存中。

(2) 动态调用,即显式调用方式,是由编程者用 API函数加载和卸载 DLL来达到调用DLL 的目的,比较复杂,但能更加有效地使用内存,是编制大型应用程序时的重要方式。在

Windows系统中,与动态库调用有关的函数包括:

在Windows中创建动态库也非常方便和简单。在ViSUaI C++中,可以创建不用 MFC而

直接用C语言写的DLL程序,也可以创建基于 MFC类库的DLL程序。每一个DLL必须有一个入口点,在VC++中,DIIMain是一个缺省的入口函数。DllMain负责初始化(InitializatiOn)和结束(Termination)工作。动态库输出函数也有两种约定,分别是基于调用约定和名字修饰

约定。DLL程序定义的函数分为内部函数和导出函数,动态库导出的函数供其它程序模块调

用。通常可以有下面几种方法导出函数:

①采用模块定义文件的EXPoRT部分指定要输入的函数或者变量。

②使用MFC提供的修饰符号_declspec(dllexport)。

③以命令行方式,采用/EXPORT命令行输出有关函数。

在Windows动态库中,有时需要编写模块定义文件(.DEF),它是用于描述 DLL属性的

模块语句组成的文本文件。

2.2 LinUX共享对象技术

在LinUX操作系统中,采用了很多共享对象技术( Shared ObjeCt ),虽然它和 Windows 里的动态库相对应,但它并不称为动态库。相应的共享对象文件以.so作为后缀,为了方便,在本文中,对该概念不进行专门区分。LinUX系统的/Iib以及标准图形界面的∕usr∕X11R6∕lib 等目录里面,就有许多以so结尾的共享对象。同样,在LinUX下,也有静态函数库这种调

用方式,相应的后缀以.a结束。LinUX采用该共享对象技术以方便程序间共享,节省程序占有空间,

本文来源:https://www.bwwdw.com/article/kfxl.html

Top