GCC静态库和动态库

什么是库:

个人理解就是把这些常用函数的目标文件打包在一起,提供相应函数的接口,便于程序员使用,库是写好的,现有的,成熟的,可以复用的代码,我们只需要知道其接口如何定义,便可以自如使用。
格式:
在linux中,静态库是以.a为后缀的文件,共享库是以.so为后缀的文件。
在windows中,静态库是以.lib为后缀的未见,共享库是以.dll为后缀的文件。
**静态库:**静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要静态库。
**动态库:**动态库在程序编译时并不会被连接到目标代码中,而是在程序运行时才被载入,因此在程序运行时还需要动态库的存在。

库的生成

linux下的静态库和动态库
静态库:
1.首先将源文件编译成目标文件:gcc -c a.c b.c
2.生成静态库:ar -rc libstatic.a a.o b.o

共享库:
1. 同静态库一样编译成目标文件:gcc -c a.c b.c
2. 生成共享库:gcc -fPIC -shared -o libshared.so a.o b.o
** 静态库和动态库都是对目标文件的处理,也可以说库文件已经是机器码文件了,静态库和共享库的加载过程有很大的区别。**
静态库的链接方法:
gcc -o staticcode -L. -lstatic main.c -static(默认库在当前文件夹)
共享库的链接方法:
gcc -o sharedcode -L. -lshared main.c(默认库在当前文件夹)

当程序与静态库链接时,库中目标文件所含的所有将被程序使用的函数的机器码都被copy到最终的可执行文件中。这就会导致最终生成的可执行代码量相对变多,相对编译器将代码补充完成了,这样运行起来相对快些。
编译过程中已经被载入可执行程序。
缺点就是占用磁盘和内存空间。静态库会被添加到和它连接的每个程序中,而且这些程序运行时,都会被加载到内存中,无形中又多消耗了更多的内存空间。

与共享库连接的可执行文件只包含它需要的函数的引用表,而不是所有的函数代码,只有在程序执行时,**那些需要的函数代码才被拷贝到内存中。**这样就使可执行文件比较小,节省磁盘空间,更进一步,操作系统使用虚拟内存,使得一份共享库驻留在内存中被多个程序使用,也同时节约了内存。不过由于运行时要去链接库会花费一定地时间,执行速度相对会慢一些,总的来说静态库是牺牲了空间效率,换取了时间效率,共享库是牺牲了时间效率换取了空间效率没有好与坏的区别,只看具体需要了。

此外,一个程序编好后,有时需要做一些修改和优化,如果我们要修改的刚好是库函数的话,在接口不变的前提下,使用共享库的程序只需要将共享库编译就可以了,而使用静态库的程序则需要将静态库重新编译好后,将程序再重新编译一遍。

可执行程序在执行的时候如何定位共享库文件

当系统加载可执行代码的时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。
此时就需要系统动态载入器(dynamiclinker/loader)
对于elf格式的可执行程序,是由ld-linux.so*来完成的
他先后搜索elf文件中的DT_RPATH段——环境变量LD_LIBRARY_PATH-/etc/ld.so.cache文件列表-/lib/./usr/lib目录找到库文件后将其载入内存。

新安装一个库之后如何让系统能够找到他

如果安装在/lib或者/usr/lib下,那么ld默认就能找到他,不需要其他操作。
如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下

  1. 编译/etc/ld.so.conf文件,加入库文件所在目录的路径。
  2. 运行ldconfig,该命令会重建/etc/ld.so.cache文件。

静态库

在linux环境中,使用ar命令创建静态库文件,如下是命令的选项:
d-----从指定的静态库文件中删除文件
m-----把文件移动到指定的静态库文件中
p-----把静态库文件中指定的文件输出到标准输出
q-----快速地把文件追加到静态库文件中
r-----把文件插入到静态库文件中
t-----显示静态库文件中文件的列表
x-----从静态库文件中提取文件
还有多个修饰符修改以上基本选项,详细看man ar以下列出三个:
a-----把新的目标文件(*.o)添加到静态库文件中现有文件之后。
b-----***************************************之前
v-----使用详细模式

ar的命令格式:
ar[-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files…
参数archive定义库的名称,files是库文件中包含的目标文件的清单,用空格分割每个文件。

比如创建一个静态库文件的命令如下:
ar r libapue.a error.oerrorlog.o lockreg.o
这样就生成了libapue.a静态库文件,可以用t选项显示包含在库中的文件
创建库文件之后,可以创建这个静态库文件的索引来帮助提高和库连接的其他程序的编译速度:
使用ranlib程序创建库的索引,索引存放在库文件内部。

	ranlib libapue.a

用nm程序显示存档文件的索引,他可以显示目标文件的符号

			nm libqpue.a | more

如果是显示目标文件的符号:

nm error.o | more

如何使用?如下所示:

gcc -o test test,c libqpue.a

这样就可以在test.c中调用libapue.a中的函数了。

动态库

创建动态库

gcc -shared -o libapue.soerror.o errirlog.o

这样就创建了共享库

编译共享库

假设共享库位于当前目录(即跟程序文件相同的目录中)

gcc -o test -L. -lapue test.c

这样就编译除了不包含函数diamante可执行文件了,但是当你运行时会发现linux动态加载器找不到libapue.so文件。
可以用ldd命令查看可执行文件依赖什么共享库:
ldd test
如何才能让动态加载器发现库文件呢?
1.环境变量
exportLD_LIBRARY_PATH="$LD_LIBRARY_PATH:."
2.修改/etc/ld.so.conf文件
一般应用程序的库文件不与系统库文件放在同一个目录下,一般把应用程序的共享库文件放在/usr/local/lib下,新建一个属于自己的目录apue,然后把刚才libapue.so复制过去就行了。
同时在/etc/ld.so.conf中新增一行:

/usr/local/lib/apue

以后在编译程序是加上编译选项:

-L/usr/local/lib/apue -lapue

参数的配置通过mangcc可以看到

-llibrary
连接名为library的库文件
链接器在标准搜索目录中寻找这个库文件,库文件的真正名字。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值