Chinaunix

标题: 问个.a和.so的区别 [打印本页]

作者: linkejin    时间: 2008-12-11 21:55
标题: 问个.a和.so的区别
首先a.so(b.a)可以和b.so(或者b.a)可以生成一个大的.a或者.so吗?为什么不能生成,不是.a和.so都是.o的集合,为什么不能继续压缩呢?
其次如果生成a应用,要链接库b.so和c.so,b和c相应引用接口,-la,-lb链接时候会报错
是否应该这样引用-lb -lc -lb,makefile在b中找到不认识的符号是不是到后续的库中重定位,还是在a链接的所有的库中去找定义呢
作者: cjaizss    时间: 2008-12-11 22:45
呵呵,可能你对库存在一点误解
作者: waker    时间: 2008-12-12 08:10
大婶,这里是男厕所
作者: 雨过白鹭洲    时间: 2008-12-12 09:15
你只管你要用的接口,不用管库本身又了谁谁谁的接口

当然,所有依赖的库,你必须让系统能够找到
作者: futuregod    时间: 2008-12-12 09:29
原帖由 linkejin 于 2008-12-11 21:55 发表
首先a.so(b.a)可以和b.so(或者b.a)可以生成一个大的.a或者.so吗?为什么不能生成,不是.a和.so都是.o的集合,为什么不能继续压缩呢?
其次如果生成a应用,要链接库b.so和c.so,b和c相应引用接口,-la,-lb链 ...


链接出错了? 把你的代码贴上来。

.a 和.so自然是不一样的。三言两语是讲不清楚的。一般讨论.a和.so之类的,都需要好几页呢。
google   linux dynamic , static library


另, 可以看看linker and loader. 你肯定就明白了。
作者: linkejin    时间: 2008-12-15 18:41
我试了下链接的时候,如果a.so和b.so互相引用的话
这样写makefile就没问题了:-la -lb -la
我记得有makefile的书上写,链接的时候,如果a库里面有未定义的符号的时候,它会到a库之后的库去找,上述例子就阐述了这一点,另外我看到内核的makefile里面也有类似-la -lb -la的用法
但是有的时候makefile在链接的时候,又不讲究这种顺序,比如a.so依赖b.so ,我可以这样写-lb -la或者-la -lb。这个由于源码包太大太多,不好把例子发上来,那个例子也不是我写的,我只负责链接成功就可以。
就觉得相当奇怪,makefile链接的时候到底是个什么样子的过程。
有的时候还很奇怪,我如果把所有的.o文件生成一个可执行文件是200多k,但是呢如果有的时候我一些.o先生成.a,然后再链接.o和.a生成一个可执行文件,有200k左右,发现一定要按照一定顺序去写链接的库名,不然生成的可执行文件只有7k,这个例子可以参照upnp的源码编译。
作者: langue    时间: 2008-12-15 21:34
标题: 回复 #1 linkejin 的帖子
你这个思维已经完全乱掉了。

.a 就是 archive
.so 就是 shared object

Archive 相当于某个人(这个可能是你也可能是别人)在编一个程序的时候中途留下了很多 .o 文件没用光。怎么办?Archive 起来,以后写别的程序用得着。所以你的程序如果用了 archive,连接到的是“静态”库,库好像已经和你的程序化为一体,不分彼此。

Shared object 呢?你的心态又不一样了。你写程序,写着写着发现很多程序都要用到同一段代码,怎么办?直接 copy 过去省事啊,不过维护起来麻烦。用 archive?也还行,只是有点浪费空间了。那怎么办?一拍大腿,点子来了,share 一下这个 object,这样既方便维护,又节省空间。

现实环境里两种情况都有,自己想想清楚每一种的目的是要干啥就行了。
作者: samon_fu    时间: 2008-12-16 03:49
标题: 回复 #1 linkejin 的帖子
C版这种问题太多了,LZ搜索下历史的帖子吧,动态库和静态库不一样的,很不一样的,LS也解释的很清楚了。
作者: c/unix    时间: 2008-12-16 11:52
提示: 作者被禁止或删除 内容自动屏蔽
作者: net_robber    时间: 2008-12-16 11:56
原帖由 linkejin 于 2008-12-15 18:41 发表
我试了下链接的时候,如果a.so和b.so互相引用的话
这样写makefile就没问题了:-la -lb -la
我记得有makefile的书上写,链接的时候,如果a库里面有未定义的符号的时候,它会到a库之后的库去找,上述例子就阐述 ...



-la使用的 是 liba.XX 而不是 a.XX
作者: xxq31217    时间: 2012-11-09 17:27
langue和c/unix 回答的真好!
我也受益匪浅,我的感觉就是静态库是写入程序中的,静态库文件与.o文件是平级关系,
而动态库是已经编译好的,如.dll、.so,它与可执行程序是平行关系。
    .a是archive
      .so是shared object
学到了
作者: Ager    时间: 2012-11-09 17:30
c/unix 发表于 2008-12-16 11:52
1.什么是库
在windows平台和linux平台下都大量存在着库。
本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
由于windows和linux的本质不同,因此二者库的二进制是不兼容的。
本文仅限于介绍linux下的库。


2.库的种类
linux下的库有两种:静态库和共享库(动态库)。
二者的不同点在于代码被载入的时刻不同。
静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。
共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。


3.库存在的意义
库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。
现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。


4.库文件是如何产生的在linux下
静态库的后缀是.a,它的产生分两步
Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表
Step 2.ar命令将很多.o转换成.a,成文静态库
动态库的后缀是.so,它由gcc加特定参数编译产生。
例如:
$ gcc -fPIC -c *.c $ gcc -shared -Wl,-soname, libfoo.so.1 -o libfoo.so.1.0 *.


5.库文件是如何命名的,有没有什么规范
在linux下,库文件一般放在/usr/lib /lib下,
静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称
动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号


6.如何知道一个可执行程序依赖哪些库
ldd命令可以查看一个可执行程序依赖的共享库,
例如# ldd /bin/lnlibc.so.6
=> /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2
=> /lib/ld- linux.so.2 (0×40000000)
可以看到ln命令依赖于libc库和ld-linux库


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


8.在新安装一个库之后如何让系统能够找到他
如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。
如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下
1.编辑/etc/ld.so.conf文件,加入库文件所在目录的路径
2.运行ldconfig,该命令会重建/etc/ld.so.cache文件


Marked....
作者: NalaGinrut    时间: 2012-11-09 17:33
waker 发表于 2008-12-12 08:10
大婶,这里是男厕所


正解 [padding for posting 0000000000]
作者: ilogo1    时间: 2012-11-21 14:40
动态库有两种加载方式,一种是系统在加载可执行目标文件时由动态连接器解析编译时未重定位的符号,编译时必须提供需要链接的动态链接库;还有一种是在程序加载后,执行时有动态加载器动态加载。。dlopen....四个函数。。。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2