LINUX動態庫檔案 soname realname linkname 詳解
先明白動態庫檔案的3個名字
soname :透過gcc/g++ -soname,libtest2.so.1 設定他是程式中連線檔案的時候找的檔案,本身為一個連線,他包含大版本,如果任何小版本的變化,直接替換到
realname,然後ln -s 建立同樣的soname 到新的realname檔案即可,不需要重新編譯程式。
realname:是動態庫檔案的真實的名字及-o libtest2.so.1.1 生成的,sonanme 軟連線指向它,雖然程式連線的時候找到的soname但是透過連線找到實際的
realname,他包含大版本和小版本。
linkname:這個可有可無,但是如果要,他不包含版本資訊,在g++的時候應該使用這個名字,避免版本改動重新編譯makefile,如果哪天大版本也發生了變化
使用linkname是版本無關的任然能夠編譯透過。我們只需要重新建立linkname的指向到新版本即可
比如:
libtest2.so.1.1 為realname
libtest2.so.1 為soname
libtest2.so 為linkname
編譯或者使用makefile的時候應該儘量使用linkname,而不是使用realname
如
g++ main.cpp libtest2.so
1、生成目標檔案,二進位制機器碼未連線,使用-c,-g為可以除錯
g++ -fPIC -c -g t2.cpp {可以多個}
生成.o的機器碼檔案沒有連線 -fPIC程式碼位置無關
2、生成動態庫檔案
g++ -shared -Wl,-soname,libtest2.so.1 -o libtest2.so.1.1 t2.o {可以多個}
生成soname為libtest2.so.1真實名字為libtest2.so.1.1的動態庫檔案檔名字為relname
1.1為主版本和發行版
readelf -d libtest2.so.1.1
可以檢視soname和relname
3、生成soname軟連線
/etc/ld.so.conf 加入一行 /home/gaopeng/CPLUSPLUS/part9
執行ldconfig自動生成soname
同時搜尋庫檔案檔案也會搜尋/etc/ld.so.conf的新配置的目錄下的soname
或者指定目錄生成soname
ldconfig -n /home/gaopeng/CPLUSPLUS/part9
生成連線連線實際上就是soname指向realname
或者
也可以使用ln -s 來建立soname
ln -s /home/gaopeng/CPLUSPLUS/part9/libfu.so.1.1 /home/gaopeng/CPLUSPLUS/part9/libfu.so.1
後兩種方式需要修改
LD_LIBRARY_PATH環境變數指向這個目錄/home/gaopeng/CPLUSPLUS/part9/
因為預設不會再自定義的目錄下面早除非指定了
/etc/ld.so.conf並且ldconfig生效了
4、
g++ main.cpp libtest2.so.1.1 不推薦這種方式應該使用linkname見下面
5、
ldd a.out
檢視程式需要的庫檔案,這裡表示出來的是soname位置,而不是rename或者linkname
程式動態連線實際上如果有soname就會找到soname
建立linkname
如 lns -s libtest2.so.1.1 libtest2.so
這裡的libtest2.so 就是一個link name
那麼我們編譯的時候
就是
g++ main.cpp libtest2.so 代替掉第四步
使用者的soname和realname檔案及linkname檔案全部放到 /usr/lib下,這種情況下只要有soname正確的指向了,就
不需要修改,當然也可以隨意
這裡使用soname放到/usr/lib下其他放到當前目錄
當前realname檔案在目錄/home/gaopeng/CPLUSPLUS/part9/
生成soname,使用ln -s方法
sudo ln -s /home/gaopeng/CPLUSPLUS/part9/libfu.so.1.1 /usr/lib/libfu.so.1
sudo ln -s /home/gaopeng/CPLUSPLUS/part9/libfu2.so.1.10 /usr/lib/libfu2.so.1
生成linkname,使用ln -s
gaopeng@bogon:~/CPLUSPLUS/part9$ ln -s libfu.so.1.1 libfu.so
gaopeng@bogon:~/CPLUSPLUS/part9$ ln -s libfu2.so.1.10 libfu2.so
gaopeng@bogon:~/CPLUSPLUS/part9$ g++ main.cpp libfu.so libfu2.so
gaopeng@bogon:~/CPLUSPLUS/part9$ ldd a.out
linux-vdso.so.1 => (0x00007ffccb799000)
libfu.so.1 => /usr/lib/libfu.so.1 (0x00007f1be882e000)
libfu2.so.1 => /usr/lib/libfu2.so.1 (0x00007f1be862c000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1be8328000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1be7f63000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1be7c5d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1be8a31000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1be7a47000)
如果mv任何一個realname檔案出錯
gaopeng@bogon:~/CPLUSPLUS/part9$ mv libfu.so.1.1 libfu.so.1.1bak
gaopeng@bogon:~/CPLUSPLUS/part9$ ./a.out
./a.out: error while loading shared libraries: libfu.so.1: cannot open shared object file: No such file or directory
gaopeng@bogon:~/CPLUSPLUS/part9$ ldd a.out
linux-vdso.so.1 => (0x00007ffcedde5000)
libfu.so.1 => not found ---這裡soname就找不到了
libfu2.so.1 => /usr/lib/libfu2.so.1 (0x00007fd86e4f1000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fd86e1ed000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd86de28000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd86db22000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd86e6f3000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fd86d90c000)
當然soname也可以放到任何目錄,如我隨意放了一個目錄為
/home/gaopeng/CPLUSPLUS/part9/lib
而
realname檔案在
/home/gaopeng/CPLUSPLUS/part9
那麼顯然在/usr/lib下找不到這個soname,那麼我們需要做的就是
export LD_LIBRARY_PATH=/home/gaopeng/CPLUSPLUS/part9/lib
讓g++程式能夠找到這個soname,或者修改/etc/ld.so.conf並且ldconfig生效了
但是一般情況下linkname soname realname都在同一個目錄下,這裡只是想說明
程式執行的時候要找的只是soname的位置,而soname指向了realname
最後
g++ t2.cpp -fPIC -shared -o libtest2.so.1.10 不生成soname 的方式,不推薦這種方式,這種方式
readelf -d libmysqlclient.so.20.3.0 readelf可以檢視soname及依賴庫檔案
Dynamic section at offset 0x39ead8 contains 29 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED) Shared library: [librt.so.1]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [libmysqlclient.so.20]
0x000000000000000c (INIT) 0x25d90
0x000000000000000d (FINI) 0xb81e8
0x000000006ffffef5 (GNU_HASH) 0x1b8
0x0000000000000005 (STRTAB) 0x1eb0
0x0000000000000006 (SYMTAB) 0x5a8
0x000000000000000a (STRSZ) 3872 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000003 (PLTGOT) 0x59f9f0
0x0000000000000002 (PLTRELSZ) 3960 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x24e18
0x0000000000000007 (RELA) 0x3128
0x0000000000000008 (RELASZ) 138480 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffc (VERDEF) 0x2fe8
0x000000006ffffffd (VERDEFNUM) 3
0x000000006ffffffe (VERNEED) 0x3048
0x000000006fffffff (VERNEEDNUM) 6
0x000000006ffffff0 (VERSYM) 0x2dd0
0x000000006ffffff9 (RELACOUNT) 5506
0x0000000000000000 (NULL) 0x0
soname :透過gcc/g++ -soname,libtest2.so.1 設定他是程式中連線檔案的時候找的檔案,本身為一個連線,他包含大版本,如果任何小版本的變化,直接替換到
realname,然後ln -s 建立同樣的soname 到新的realname檔案即可,不需要重新編譯程式。
realname:是動態庫檔案的真實的名字及-o libtest2.so.1.1 生成的,sonanme 軟連線指向它,雖然程式連線的時候找到的soname但是透過連線找到實際的
realname,他包含大版本和小版本。
linkname:這個可有可無,但是如果要,他不包含版本資訊,在g++的時候應該使用這個名字,避免版本改動重新編譯makefile,如果哪天大版本也發生了變化
使用linkname是版本無關的任然能夠編譯透過。我們只需要重新建立linkname的指向到新版本即可
比如:
libtest2.so.1.1 為realname
libtest2.so.1 為soname
libtest2.so 為linkname
編譯或者使用makefile的時候應該儘量使用linkname,而不是使用realname
如
g++ main.cpp libtest2.so
1、生成目標檔案,二進位制機器碼未連線,使用-c,-g為可以除錯
g++ -fPIC -c -g t2.cpp {可以多個}
生成.o的機器碼檔案沒有連線 -fPIC程式碼位置無關
2、生成動態庫檔案
g++ -shared -Wl,-soname,libtest2.so.1 -o libtest2.so.1.1 t2.o {可以多個}
生成soname為libtest2.so.1真實名字為libtest2.so.1.1的動態庫檔案檔名字為relname
1.1為主版本和發行版
readelf -d libtest2.so.1.1
可以檢視soname和relname
3、生成soname軟連線
/etc/ld.so.conf 加入一行 /home/gaopeng/CPLUSPLUS/part9
執行ldconfig自動生成soname
同時搜尋庫檔案檔案也會搜尋/etc/ld.so.conf的新配置的目錄下的soname
或者指定目錄生成soname
ldconfig -n /home/gaopeng/CPLUSPLUS/part9
生成連線連線實際上就是soname指向realname
或者
也可以使用ln -s 來建立soname
ln -s /home/gaopeng/CPLUSPLUS/part9/libfu.so.1.1 /home/gaopeng/CPLUSPLUS/part9/libfu.so.1
後兩種方式需要修改
LD_LIBRARY_PATH環境變數指向這個目錄/home/gaopeng/CPLUSPLUS/part9/
因為預設不會再自定義的目錄下面早除非指定了
/etc/ld.so.conf並且ldconfig生效了
4、
g++ main.cpp libtest2.so.1.1 不推薦這種方式應該使用linkname見下面
5、
ldd a.out
檢視程式需要的庫檔案,這裡表示出來的是soname位置,而不是rename或者linkname
程式動態連線實際上如果有soname就會找到soname
建立linkname
如 lns -s libtest2.so.1.1 libtest2.so
這裡的libtest2.so 就是一個link name
那麼我們編譯的時候
就是
g++ main.cpp libtest2.so 代替掉第四步
使用者的soname和realname檔案及linkname檔案全部放到 /usr/lib下,這種情況下只要有soname正確的指向了,就
不需要修改,當然也可以隨意
這裡使用soname放到/usr/lib下其他放到當前目錄
當前realname檔案在目錄/home/gaopeng/CPLUSPLUS/part9/
生成soname,使用ln -s方法
sudo ln -s /home/gaopeng/CPLUSPLUS/part9/libfu.so.1.1 /usr/lib/libfu.so.1
sudo ln -s /home/gaopeng/CPLUSPLUS/part9/libfu2.so.1.10 /usr/lib/libfu2.so.1
生成linkname,使用ln -s
gaopeng@bogon:~/CPLUSPLUS/part9$ ln -s libfu.so.1.1 libfu.so
gaopeng@bogon:~/CPLUSPLUS/part9$ ln -s libfu2.so.1.10 libfu2.so
gaopeng@bogon:~/CPLUSPLUS/part9$ g++ main.cpp libfu.so libfu2.so
gaopeng@bogon:~/CPLUSPLUS/part9$ ldd a.out
linux-vdso.so.1 => (0x00007ffccb799000)
libfu.so.1 => /usr/lib/libfu.so.1 (0x00007f1be882e000)
libfu2.so.1 => /usr/lib/libfu2.so.1 (0x00007f1be862c000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1be8328000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1be7f63000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1be7c5d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1be8a31000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1be7a47000)
如果mv任何一個realname檔案出錯
gaopeng@bogon:~/CPLUSPLUS/part9$ mv libfu.so.1.1 libfu.so.1.1bak
gaopeng@bogon:~/CPLUSPLUS/part9$ ./a.out
./a.out: error while loading shared libraries: libfu.so.1: cannot open shared object file: No such file or directory
gaopeng@bogon:~/CPLUSPLUS/part9$ ldd a.out
linux-vdso.so.1 => (0x00007ffcedde5000)
libfu.so.1 => not found ---這裡soname就找不到了
libfu2.so.1 => /usr/lib/libfu2.so.1 (0x00007fd86e4f1000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fd86e1ed000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd86de28000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd86db22000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd86e6f3000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fd86d90c000)
當然soname也可以放到任何目錄,如我隨意放了一個目錄為
/home/gaopeng/CPLUSPLUS/part9/lib
而
realname檔案在
/home/gaopeng/CPLUSPLUS/part9
那麼顯然在/usr/lib下找不到這個soname,那麼我們需要做的就是
export LD_LIBRARY_PATH=/home/gaopeng/CPLUSPLUS/part9/lib
讓g++程式能夠找到這個soname,或者修改/etc/ld.so.conf並且ldconfig生效了
但是一般情況下linkname soname realname都在同一個目錄下,這裡只是想說明
程式執行的時候要找的只是soname的位置,而soname指向了realname
最後
g++ t2.cpp -fPIC -shared -o libtest2.so.1.10 不生成soname 的方式,不推薦這種方式,這種方式
readelf -d libmysqlclient.so.20.3.0 readelf可以檢視soname及依賴庫檔案
Dynamic section at offset 0x39ead8 contains 29 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED) Shared library: [librt.so.1]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [libmysqlclient.so.20]
0x000000000000000c (INIT) 0x25d90
0x000000000000000d (FINI) 0xb81e8
0x000000006ffffef5 (GNU_HASH) 0x1b8
0x0000000000000005 (STRTAB) 0x1eb0
0x0000000000000006 (SYMTAB) 0x5a8
0x000000000000000a (STRSZ) 3872 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000003 (PLTGOT) 0x59f9f0
0x0000000000000002 (PLTRELSZ) 3960 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x24e18
0x0000000000000007 (RELA) 0x3128
0x0000000000000008 (RELASZ) 138480 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffc (VERDEF) 0x2fe8
0x000000006ffffffd (VERDEFNUM) 3
0x000000006ffffffe (VERNEED) 0x3048
0x000000006fffffff (VERNEEDNUM) 6
0x000000006ffffff0 (VERSYM) 0x2dd0
0x000000006ffffff9 (RELACOUNT) 5506
0x0000000000000000 (NULL) 0x0
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2120139/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Linux共享庫、靜態庫、動態庫詳解Linux
- Linux 動態庫與靜態庫製作及使用詳解Linux
- linux的啟動配置檔案inittab檔案詳解Linux
- linux 動態庫檔案stripped屬性理解Linux
- 共享庫soname機制
- Linux檔案系統詳解Linux
- 【Linux/etc/profile檔案詳解 】Linux
- Linux 檔案系統詳解Linux
- 詳解Linux中/etc/passwd檔案Linux
- linux網路卡配置檔案詳解Linux
- linux檔案許可權 詳解Linux
- Linux檔案許可權詳解Linux
- Linux 依賴動態庫 / 靜態庫的動態態庫 / 靜態庫Linux
- Linux動態庫Linux
- Linux檔案相關命令詳解(一)Linux
- linux下檔案打包、壓縮詳解Linux
- Linux etc目錄配置檔案詳解Linux
- Linux 解壓zip檔案詳解之unzip命令!Linux
- C編譯: 動態連線庫 (.so檔案)編譯
- Linux下的靜態庫、動態庫和動態載入庫Linux
- fstab檔案詳解及Linux下自動掛載windows分割槽[轉]LinuxWindows
- MongoDB啟動檔案配置引數詳解MongoDB
- Linux 裝置檔案/dev/*詳解、查詢Linuxdev
- 詳解Linux指令與檔案的搜尋Linux
- Linux常用檔案許可權命令詳解Linux
- Linux斷點續傳檔案功能詳解Linux斷點
- Linux網路卡配置檔案 引數詳解Linux
- Linux中./configure檔案配置詳解Linux
- Linux 系統配置檔案詳細解讀Linux
- Linux中/proc目錄下檔案詳解Linux
- 資料庫控制檔案中的SCN詳解資料庫
- Dockerfile檔案詳解Docker
- mtl檔案詳解
- cmake檔案詳解
- BMP檔案詳解
- LD檔案詳解
- JDK動態代理詳解JDK
- Mybatis 動態 SQL 詳解MyBatisSQL