Linux下动态链接库文件的realname、soname和linkname
1、为什么要使用这种规则?在windows平台下存在dll hell.问题,即由于dll升级之后程序无法使用升级后的dll从而导致程无法运行,也就是说动态库的新版本不能兼容旧版本。而在linux下也存在着类似的问题,为了解决这个问题,引入了这种机制。遵循这种机制制作动态库,就可以解决这种问题。但是这种规则只是一种约定,并非强制的。这种机制是通过文件名来控制动态库的版本,设计了3类命名方式,来实..
·
1、为什么要使用这种规则?
在windows平台下存在dll hell.问题,即由于dll升级之后程序无法使用升级后的dll从而导致程无法运行,也就是说动态库的新版本不能兼容旧版本。而在linux下也存在着类似的问题,为了解决这个问题,引入了这种机制。遵循这种机制制作动态库,就可以解决这种问题。但是这种规则只是一种约定,并非强制的。
这种机制是通过文件名来控制动态库的版本,设计了3类命名方式,来实现避免dll hell问题。
2、realname、soname和linkname介绍
1)realname:
- 实际等同于库文件的filename,是在库文件生成时就被指定的,可以使用命令gcc -shared -o $(realname) dependence flags 指定。
- realname的一般格式为lib$(name).so.$(major).$(minor).$(revision),$(name)是动态库的名字,$(major).$(minor).$(revision)分别表示主版本号,子版本号和修正版本号。
2)soname(Short for shared object name):
- 在库文件生成时被指定,可以使用命令gcc -shared -o $(realname) dependence flags −Wl,−soname,$(soname)指定。如
#同时指定realname和soname
gcc hello.c -shared -fPIC -Wl,-soname,libhello.so.0 -o libhello.so.0.0.0
- 其一般格式为lib$(name).so.$(major).$(minor),即lib+动态库名+.so+主版本号,soname会被写入库文件中。
- 可以使用readelf -d $(realname)查看库文件的soname。如
- 不同realname的库文件可以有相同的soname,有利于库文件的升级和兼容,例如当版本从1.0.0升级到1.0.1,库文件的接口没有变化(或者接口增加,但原有接口不变)的情况下,可以指定相同的soname,这样使用1.0.0生成的程序仍然可以运行。
- soname在链接和加载库文件时使用,当编译时使用−l $(name)链接库文件时,链接器会读取lib$(name).so文件中的soname值,并将其记录在生成的程序中,当运行程序时,会从相应的目录加载名为$(name).so文件中的soname值,并将其记录在生成的程序中,当运行程序时,会从相应的目录加载名为$(soname)的文件,所以,在运行程序之前,$(soname)的库文件必须已生成。
- 可以采用软连接的方式生成该文件,如:ln -s $(realname) $(soname)。
- 也可以使用ldconfig命令自动生成,如 ldconfig -n $(dir)会生成(dir)目录下所有库文件对应的$(soname)文件。
3)linkname:
- 在链接时使用,一般格式为lib$(name).so,通常是$(realname)文件或者$(soname)文件的软链接。如
#将linkname和soname关联起来
ln -s libhello.so.0 libhello.so
- 当使用−l $(name)选项时,链接器会从相应目录链接lib$(name).so的文件,如果该文件不存在,则会链接lib$(name).a文件,如果该文件也不存在,会发生链接错误。
- 如果链接的是lib$(name).a文件,在运行程序时也就没$(realname)文件和$(soname)文件什么事了。
总结
- 在可执行程序链接共享库时:首先会用到共享库的连接文件名,通过连接文件名找到共享库; 然后会取出共享库的简短文件名,并写在共享库自己的文件头里面。
- 在可执行程序加载共享库时: 通过共享库的简短文件名在给定的路径下寻找共享库。
参考资料
https://www.cnblogs.com/wghost/p/4131100.html
https://www.linuxidc.com/Linux/2016-06/132669.htm
更多推荐
已为社区贡献1条内容
所有评论(0)