

库是一个包含多个目标文件的文件,在程序编译的链接阶段使用。 目标文件(在Linux中以.o结尾)是编译的输出。 它们包含不能自行执行的功能的二进制代码。 回想一下C程序的编译步骤,编译的链接阶段涉及从多个目标文件制作单个可执行文件。 许多程序需要做相同的事情并使用相同的功能,那么为什么不将这些功能的代码都放在一个地方并允许不同的程序调用它们呢? 这是图书馆发挥作用的地方。 库可帮助加快链接过程,因为它们将链接器必须搜索和打开的文件数量减至最少,因为程序所需的功能全部集中在一个位置。 而且,对库进行了索引,从而简化了在符号中查找符号(即函数,变量等)的过程。 简而言之,将目标文件组织在库中的程序将大大加快链接过程。
Unix中通常有两种类型的库:静态库和动态库。 静态库在编译的链接阶段链接到程序中,而动态或共享库在运行时通过两个步骤链接。
首先让我们谈谈动态库。
动态链接器将库的单个副本链接到多个程序之间,以便所述程序可以共享对库的访问。 这些共享库在执行时由程序加载到内存中。 以下任何程序将使用已加载的共享库。
首先,链接器确认该程序将使用的所有符号都已链接到程序本身或其共享库之一中。 然后,在程序运行时,动态加载程序检查哪些共享库与程序链接,将这些库加载到内存中,并将它们附加到内存中的程序副本中。 例如,标准C库是所有C程序都使用的共享库。 但是,在任何给定时间,库中只有一个副本存储在内存中。 这样可以总体上减少运行程序所需的内存,生成较小的可执行文件,并节省磁盘空间。
静态库呢?
编译C程序时,将生成目标代码,并且计算机将在链接器上调用以使库函数的可执行代码(例如printf())以两种可能的方式提供给C程序:1)链接器复制库的代码函数到目标代码或2)链接器安排库函数的完整代码在运行时可用,而无需复制任何内容。
静态链接和静态库由链接器生成,该链接器将所有使用的库函数复制到可执行文件。 静态链接会创建较大的二进制文件,这会占用大量磁盘空间和主内存。
1.创建一个使用静态库中的函数的.c
文件
emacs测试


2.为该库创建一个.h
头文件。
emacs标头


3.编译库文件。
gcc -c -Wall -Werror -Wextra -pedantic * .c
4.创建一个静态库。
ar -rc库.a * .o
这将创建一个称为library.a的静态库。
5.在库中创建一个索引。
ranlib库
好极了! 您只是创建了自己的静态库。 现在可以使用了。
- 要使用您刚刚在程序中创建的library.a文件,请执行以下操作:
gcc main.c -L。 -图书馆-o问候
这将使用main.o和“库”静态库中所需的符号创建程序。 将库的名称添加到提供给链接器的目标文件名列表中。 注意,我们省略了.a
后缀,因为链接器会找到模式“ library”以创建要搜索的文件的名称。 -L.
标志使链接器知道搜索当前目录(由.
表示)以及标准目录。 它指示静态库在当前文件夹中。
2.运行程序
./问候
_puts函数是从您的静态库中调用的。
输出:
你好朋友!
- 创建一个使用静态库中的函数的
.c
文件
emacs测试


2.为该库创建一个.h
头文件。
emacs标头


3.使用-fPIC
标志编译.c
文件以生成.o
文件。 -fPIC
标志启用与位置无关的代码。
gcc -Wall -Werror -Wextra -pedantic -c -fPIC * .c
4.创建一个共享库。
gcc -shared -o liball.so * .o
5.将位置添加到环境变量,以便程序知道在哪里查找库文件。
导出LD_LIBRARY_PATH =。:$ LD_LIBRARY_PATH
恭喜你! 您刚刚制作了一个动态库。 现在让我们实际使用它。
- 要使用刚刚创建的
liball.so
文件,请执行liball.so
操作:
gcc -Wall -pedantic -Werror -Wextra -L。 0-main.c -lholberton -o len
2.(可选的完整性检查)列出可执行文件所依赖的共享库依赖关系。
伦
3.执行从上一步生成的可执行文件。
./len
这应该显示预期的输出。
静态库和动态库都包含包含函数的目标文件,并提供每个函数名称的地址。
回顾一下,静态链接包括在创建程序的可执行文件时将库与主程序链接。 动态链接程序在程序运行时将库与主程序链接。
- 资源利用
动态库允许多个程序共享相同的代码,因此它们不需要具有单独的代码副本。 这样可以节省执行期间的存储和内存空间。 静态库浪费了存储和内存,因为每个程序都必须拥有自己的库副本,因此效率低下。
2.更新程序
动态链接使更新程序超级简单且节省资源。 更新程序时,必须下载新的动态库并删除旧的动态库。 静态链接使更新程序变得很繁琐,并且浪费资源。 每当更新库时,都必须重新链接整个程序,这会导致可执行文件庞大。
3.编程语言兼容性
动态库可以在各种编程语言的程序之间共享。 静态库不共享,因此它们不具有此功能。
4.自给自足
动态库未集成到使用它们的程序中,这意味着需要这些库的程序不是自给自足的。 换句话说,如果缺少动态库,则需要动态库的程序将无法运行。 对于静态库,对一个程序的库所做的任何更改都不会影响其他程序,因为它们是独立的。
5.未经授权的使用
因为动态库是可共享的,所以它可以调用未经授权的库共享。 另一方面,静态库不存在未经授权使用的风险,因为它们包含在程序内并且无法共享。
6.可破解性
动态库存在于程序之外,因此可以轻松对其进行修改。 这可能意味着黑客可以篡改确保软件保护的模块。 静态库中不存在此问题。
7.速度
通常,使用动态库的程序要比使用静态库的程序慢。