.so文件是什么?
linux下的.so文件即Shared Libraries。Shared Library 是程序运行时加载的库文件。当一个shared library 被成功的安装以后,之后启动的所有程序都会自动使用最新的shared library。也就是说,生成一个.so文件并告诉编译器它的位置之后,所有的需要引入它的程序都可以同时调用它。
使用.so文件有以下这么几个好处:
- 升级库但是可以继续支持一些程序,这些程序想要使用较老版本的,或者不向后兼容的库。
- 重写特定的库文件或者甚至可以在执行特定程序时,指定一个库文件的特定函数
- 做以上这些的时候程序甚至可以正在使用着当前的库文件
每一个shared library都有一个soname、一个real name、一个linker name。
soname有一个前缀lib、自定义的短语、后跟一个.so、还有一个版本号。如:/usr/lib/libreadline.so.3
real name是一个soname的实体,在文件名中包涵了真实的库版本号。real name相比soname添加了一个句点,一个次要版本号,另一个句点,和一个发型版本号。最后一个句点和发行版本号是可选的。次要号码和发行号码支持配置控制,使别人可以明白安装的是哪个确切的版本。
linker name是没有任何版本号的soname。如/usr/lib/libreadline.so。
管理shared libraries的关键就是将这个文件名拆开。当程序内部列出它们需要的shared libraries时,仅仅需要列出soname即可。相反的,当创建一个shared library时,你只需要创建一个特定的文件名(包括详细的版本信息)即可。当你安装了一个新版本的库时,你只需将它安装在一小部分特殊的文件夹中的一个之中,然后运行程序ldconfig。lgconfig将会检查现存的文件,并且创建real name的soname和symbolic link,同时设置好春村文件。缓存文件位于/etc/ld.so.cache。
ldconfig并不设置linker name;通常这是在库安装时干的事,然后linker name作为指向最新soname或者realname的symbolic link被创建。
symbolic link(软连接)是自己指定的。名字如: /usr/lib/libreadline.so.3.0。
linker name就是一个与/usr/lib/libreadline.so.3相关联的symbolic link。
如果以上看不懂的话,是的我也没看懂,只是大体翻译了这篇文章
LD_LIBRARY_PATH
这个路径中的库文件将被在正常寻找前首先寻找。
注意事项
- .so文件(也就是Shared Libraries)必须以lib开头,以.so结尾,比如:libalpha.so。(作为特例,一些最低级的C库并不是以lib开头的)
- 必须将自定义的文件加入到LD_LIBRARY_PATH中才能运行。
生成并测试.so文件。
aplusb.c
#include <iostream>
#include "aplusb.h"
using namespace std;
int aPlusB(int a, int b)
{
int c = a + b;
return c;
}
aplusb.h
#ifndef APLUSB_H__
#define APLUSB_H__
extern int aPlusB(int a, int b);
#endif
main.c
#include <iostream>
#include "aplusb.h"
using namespace std;
int main(void)
{
int a = 1;
int b = 2;
int c = 0;
c = aPlusB(a, b);
cout<<c<<endl;
return 0;
}
第一步:创建PIC文件
g++ -c -fPIC aplusb.c
pic代码是位置无关代码,程序运行时计算机会找文件中指定的内存地址去读取数据,但是当读取一个库文件时,库本身指定的地址必须是与内存地址无关的。此时生成了aplusb.o。注意-fPIC比-fpic兼容性要高。
-c 为编译和汇编但是不链接。
生成的.o文件为机器码。
第二步:用第一步生成的文件去创建.so文件。
g++ -shared -o libaplusb.so aplusb.o
第三步:链接
g++ -L/home/lee/JNI -o main main.c -laplusb
第四步: 保证运行时可以调用
$ export LD_LIBRARY_PATH=/home/lee/JNI:$LD_LIBRARY_PATH
至此
第五部:运行
lee@lee-computer:~/JNI$ ./main
3
结果为3。调用成功。