前言
不同版本的動態(tài)庫可能會不兼容,如果程序在編譯時(shí)指定動態(tài)庫是某個(gè)低版本,運(yùn)行是用的一個(gè)高版本,可能會導(dǎo)致無法運(yùn)行。Linux上對動態(tài)庫的命名采用libxxx.so.a.b.c的格式,其中a代表大版本號,b代表小版本號,c代表更小的版本號,我們以Linux自帶的cp程序?yàn)槔?,通過ldd查看其依賴的動態(tài)庫
$ ldd /bin/cp linux-vdso.so.1 => (0x00007ffff59df000)libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fb3357e0000)librt.so.1 => /lib64/librt.so.1 (0x00007fb3355d7000)libacl.so.1 => /lib64/libacl.so.1 (0x00007fb3353cf000)libattr.so.1 => /lib64/libattr.so.1 (0x00007fb3351ca000)libc.so.6 => /lib64/libc.so.6 (0x00007fb334e35000)libdl.so.2 => /lib64/libdl.so.2 (0x00007fb334c31000)/lib64/ld-linux-x86-64.so.2 (0x00007fb335a0d000)libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fb334a14000)
左邊是依賴的動態(tài)庫名字,右邊是鏈接指向的文件,再查看libacl.so相關(guān)的動態(tài)庫
$ ll /lib64/libacl.so* lrwxrwxrwx. 1 root root 15 1月 7 2015 /lib64/libacl.so.1 -> libacl.so.1.1.0-rwxr-xr-x. 1 root root 31280 12月 8 2011 /lib64/libacl.so.1.1.0
我們發(fā)現(xiàn)libacl.so.1實(shí)際上是一個(gè)軟鏈接,它指向的文件是libacl.so.1.1.0,命名方式符合我們上面的描述。也有不按這種方式命名的,比如
$ ll /lib64/libc.so* lrwxrwxrwx 1 root root 12 8月 12 14:18 /lib64/libc.so.6 -> libc-2.12.so
不管怎樣命名,只要按照規(guī)定的方式來生成和使用動態(tài)庫,就不會有問題。而且我們往往是在機(jī)器A上編譯程序,在機(jī)器B上運(yùn)行程序,編譯和運(yùn)行的環(huán)境其實(shí)是有略微不同的。下面就說說動態(tài)庫在生成和使用過程中的一些問題
動態(tài)庫的編譯
我們以一個(gè)簡單的程序作為例子
// filename:hello.c#include <stdio.h>void hello(const char* name){ printf("hello %s!/n", name);}// filename:hello.hvoid hello(const char* name);采用如下命令進(jìn)行編譯
gcc hello.c -fPIC -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0.1
需要注意的參數(shù)是-Wl,soname(中間沒有空格),-Wl選項(xiàng)告訴編譯器將后面的參數(shù)傳遞給鏈接器,-soname則指定了動態(tài)庫的soname(簡單共享名,Short for shared object name)
現(xiàn)在我們生成了libhello.so.0.0.1,當(dāng)我們運(yùn)行ldconfig -n .命令時(shí),當(dāng)前目錄會多一個(gè)軟連接
$ ll libhello.so.0 lrwxrwxrwx 1 handy handy 17 8月 17 14:18 libhello.so.0 -> libhello.so.0.0.1
這個(gè)軟鏈接是如何生成的呢,并不是截取libhello.so.0.0.1名字的前面部分,而是根據(jù)libhello.so.0.0.1編譯時(shí)指定的-soname生成的。也就是說我們在編譯動態(tài)庫時(shí)通過-soname指定的名字,已經(jīng)記載到了動態(tài)庫的二進(jìn)制數(shù)據(jù)里面。不管程序是否按libxxx.so.a.b.c格式命名,但Linux上幾乎所有動態(tài)庫在編譯時(shí)都指定了-soname,我們可以通過readelf工具查看soname,比如文章開頭列舉的兩個(gè)動態(tài)庫
$ readelf -d /lib64/libacl.so.1.1.0 Dynamic section at offset 0x6de8 contains 24 entries:Tag Type Name/Value0x0000000000000001 (NEEDED) Shared library: [libattr.so.1]0x0000000000000001 (NEEDED) Shared library: [libc.so.6]0x000000000000000e (SONAME) Library soname: [libacl.so.1]
新聞熱點(diǎn)
疑難解答
圖片精選