linux共享库

共享库:

1.概念

2.生成一个共享库

  • 代码结构:
    实现一个四则运算的共享库:
├── 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;
}
  • 步骤:
    第一步:将函数库代码只编译不链接,生成与位置无关的.o文件
#输入命令:
g++ -fPIC -c add.cpp sub.cpp mul.cpp dev.cpp

说明:其中,fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
结果:

├── 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表示告诉编译器将后面的参数传递给链接器,于Wl来说,它的参数分割是用","。-soname是告诉编译器共享库的soname是libmycal.so.1;生成的目标文件是libmycal.so.1.10,是共享库的realname。这里我们对soname和realname进行说明:realname是动态库文件的真实的名字,记录了共享库的主版本和次版本号,本例中libmycal.so.1.10,主版本号为1,次版本号为10;而soname只记录了共享库的主版本号,本例中的soname为libmycal.so.1,只记录了主版本号1(soname一般是个软链接,指向realname)。
结果:生成共享库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

若此时利用生成的共享库与自己编写的程序一起编译,则会报错,例如我们main.cpp与共享库一起编译:

#输入命令:
g++ main.c libmycal.so.1.10 -o app

结果:生成目标程序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

此时执行app,会报错:

./app: error while loading shared libraries: libmycal.so.1: cannot open shared object file: No such file or directory

原因:有了共享库,但没有加入系统路径。
接着我们查看app所依赖的库:

#输入命令:
ldd app

结果:

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这个库系统没有找到
第三步:修改系统配置文件,将共享库为系统所共享
首先修改配置文件,将当前共享库路径加入配置文件

#输入命令:
sudo vi /etc/ld.so.conf

说明:ld.so.conf为系统共享库的配置文件,打开后将当前路径加入即可。
之后更新库:

#输入命令:
sudo ldconfig -v

结果:自动生成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

此时再执行app,可以得到结果:

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)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容