共享庫:
1.概念
- 共享庫就是動(dòng)態(tài)鏈接庫哪怔,是在程序運(yùn)行的時(shí)候加載的函數(shù)庫弥鹦。詳細(xì)介紹:https://blog.csdn.net/Lincoln_cz/article/details/81982908
2.生成一個(gè)共享庫
- 代碼結(jié)構(gòu):
實(shí)現(xiàn)一個(gè)四則運(yùn)算的共享庫:
├── add.cpp
├── common.h
├── dev.cpp
├── main.cpp
├── mul.cpp
└── sub.cpp
common.h文件:
#ifndef _COMMONH_
#define _COMMONH_
int add(int a,int b);
int sub(int a,int b);
int mul(int a,int b);
int dev(int a,int b);
#endif
add.cpp文件:
int add(int a,int b){
return (a+b);
}
sub.cpp文件:
int sub(int a,int b){
return (a-b);
}
mul.cpp文件:
int mul(int a,int b){
return (a*b);
}
dev.cpp文件:
int dev(int a,int b){
return (a/b);
}
main.cpp文件:
#include <iostream>
#include "common.h"
using namespace std;
int main(){
cout << "begin():" <<endl;
cout << "test add:"<<add(4,1)<<endl;
cout << "test sub:"<<sub(4,1)<<endl;
cout << "test mul:"<<mul(4,1)<<endl;
cout << "test dev:"<<dev(4,1)<<endl;
return 0;
}
- 步驟:
第一步:將函數(shù)庫代碼只編譯不鏈接,生成與位置無關(guān)的.o文件
#輸入命令:
g++ -fPIC -c add.cpp sub.cpp mul.cpp dev.cpp
說明:其中寒跳,fPIC 作用于編譯階段聘萨,告訴編譯器產(chǎn)生與位置無關(guān)代碼(Position-Independent Code),則產(chǎn)生的代碼中童太,沒有絕對地址米辐,全部使用相對地址胸完,故而代碼可以被加載器加載到內(nèi)存的任意位置,都可以正確的執(zhí)行翘贮。這正是共享庫所要求的赊窥,共享庫被加載時(shí),在內(nèi)存的位置不是固定的狸页。
結(jié)果:
├── add.cpp
├── add.o
├── common.h
├── dev.cpp
├── dev.o
├── main.cpp
├── mul.cpp
├── mul.o
├── sub.cpp
└── sub.o
第二步:生成共享庫
#輸入命令:
g++ -shared -Wl,-soname,libmycal.so.1 add.o sub.o mul.o dev.o -o libmycal.so.1.10
說明:-shared表示生成共享庫锨能;-Wl表示告訴編譯器將后面的參數(shù)傳遞給鏈接器,于Wl來說芍耘,它的參數(shù)分割是用","址遇。-soname是告訴編譯器共享庫的soname是libmycal.so.1;生成的目標(biāo)文件是libmycal.so.1.10齿穗,是共享庫的realname傲隶。這里我們對soname和realname進(jìn)行說明:realname是動(dòng)態(tài)庫文件的真實(shí)的名字,記錄了共享庫的主版本和次版本號窃页,本例中l(wèi)ibmycal.so.1.10跺株,主版本號為1,次版本號為10脖卖;而soname只記錄了共享庫的主版本號乒省,本例中的soname為libmycal.so.1,只記錄了主版本號1(soname一般是個(gè)軟鏈接畦木,指向realname)袖扛。
結(jié)果:生成共享庫libmycal.so.1.10。
├── add.cpp
├── add.o
├── common.h
├── dev.cpp
├── dev.o
├── libmycal.so.1.10
├── main.cpp
├── mul.cpp
├── mul.o
├── sub.cpp
└── sub.o
若此時(shí)利用生成的共享庫與自己編寫的程序一起編譯十籍,則會(huì)報(bào)錯(cuò)蛆封,例如我們main.cpp與共享庫一起編譯:
#輸入命令:
g++ main.c libmycal.so.1.10 -o app
結(jié)果:生成目標(biāo)程序app
├── add.cpp
├── add.o
├── app
├── common.h
├── dev.cpp
├── dev.o
├── libmycal.so.1.10
├── main.cpp
├── mul.cpp
├── mul.o
├── sub.cpp
└── sub.o
此時(shí)執(zhí)行app,會(huì)報(bào)錯(cuò):
./app: error while loading shared libraries: libmycal.so.1: cannot open shared object file: No such file or directory
原因:有了共享庫勾栗,但沒有加入系統(tǒng)路徑惨篱。
接著我們查看app所依賴的庫:
#輸入命令:
ldd app
結(jié)果:
linux-vdso.so.1 (0x00007fff11b9c000)
libmycal.so.1 => not found
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f0a30697000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0a302a6000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f0a2ff08000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0a30c23000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f0a2fcf0000)
我們看到libmycal.so.1 => not found,即libmycal.so.1這個(gè)庫系統(tǒng)沒有找到
第三步:修改系統(tǒng)配置文件围俘,將共享庫為系統(tǒng)所共享
首先修改配置文件砸讳,將當(dāng)前共享庫路徑加入配置文件
#輸入命令:
sudo vi /etc/ld.so.conf
說明:ld.so.conf為系統(tǒng)共享庫的配置文件,打開后將當(dāng)前路徑加入即可界牡。
之后更新庫:
#輸入命令:
sudo ldconfig -v
結(jié)果:自動(dòng)生成soname軟連接簿寂,即下面的libmycal.so.1(指向realname)
├── add.cpp
├── add.o
├── app
├── common.h
├── dev.cpp
├── dev.o
├── libmycal.so.1 -> libmycal.so.1.10
├── libmycal.so.1.10
├── main.cpp
├── mul.cpp
├── mul.o
├── sub.cpp
└── sub.o
此時(shí)再執(zhí)行app,可以得到結(jié)果:
begin():
test add:5
test sub:3
test mul:4
test dev:4
第四步:生成linkname
#輸入命令:
ln -s libmycal.so.1.10 libmycal.so
libmycal.so為linkname宿亡,linkname相比soname和realname常遂,沒有記錄庫的版本號,一般用于makefile中挽荠,soname只記錄主版本號烈钞,realname記錄主版本和次版本泊碑。linkname和soname均指向realname。
link name(libmycal.so)->real name(libmycal.so.1.10)
so name(libmycal.so.1)->real name(libmycal.so.1.10)