1. Linux静态库
1)静态库生成
假设库名为libmylib.a,链接目标文件为mylib.o
# ar rcs libmylib.a mylib.o
2)将静态库拷贝到/usr/lib/或/lib目录下
# cp libmylib.a /usr/lib
3)静态库使用
比如测试文件为test.c
# gcc -o test test.c -lmylib
其中: -l选项,mylib为库名,Linux下约定所有库都以前缀lib开始,静态库以.a结尾,动态库以.so结尾。在编译程序时,无需带上前缀和后缀。
2. Linux动态库
动态库的创建
# gcc -fPIC -o mylib.o -c mylib.c
# gcc -shared -o libmylib.so mylib.o
也可以直接使用下面命令:
# gcc –fPIC -shared -o libmylib.so mylib.c
PCI-Position Independent Code
动态库的调用
1)# gcc -o test test.c ./libmylib.so
2)# cp libmylib.so /usr/lib
# gcc -o test test.c /usr/lib/libmylib.so
注意:应用动态库时,必须含有路径,如果只是使用libmylib.so,则必须确保这个库所在的目录包括在PATH环境变量中。编译通过但是运行提示找不到库,就是因为程序运行时找不到动态库所致的(Linux动态库的默认路径是/lib和/usr/lib),需要在/etc/ld.so.conf配置我呢就中添加路径(一般为/usr/local/lib),然后使用ldconfig命令进行更新。
3. 动态加载动态库
打开指定名字的动态链接库,返回动态库句柄:
# void *dlopen(const char *filename, int flag)
# flag = RTLD_LAZY/RTLD_NEW/RTLD_GLOBAL
根据动态库句柄和函数名,返回函数名对应的函数地址:
# void *dlsym(void *handle, char *symbol)
关闭动态链接库
# int dlclose(void *handle)
获得动态库执行失败时的错误信息
# const char *dlerror(void)
示例:
int main(void)
{
void *handle;
char *error;
void (*Welcome)();
if ((handle = dlopen(‘./libmylib.so’, RTLD_LAZY)) == NULL) {
printf(“dlopen error\n”);
return -1;
}
Welcome = dlsym(handle, “Welcome”);
if ((error = dlerror()) != NULL) {
printf(“dlsym error\n”);
return -1;
}
Welcome();
dlclose(handle);
return 0;
}
# gcc –ldl -o main main.c
其中-ldl为dlopen/dlsym/dlclose函数所在的库,使用数学库加上-lm。
库工具使用
ldd命令:用来显示执行文件需要那些共享库,共享库装载管理器在那里查找需要的共享库。
nm命令: 查看库中的符号,可以打印出库(动态库和静态库)中涉及到的所有符号。U表示在库中被调用但没有被定义;T表示库中定义的函数;W表示在库中定义,但是可能被其它库同名符号覆盖。
Tips:为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: libhello.so.1.0,由于程序连接默认以.so为文件后缀名。所以为了使用这些库,通常使用建立符号连接的方式。
ln -s libhello.so.1.0 libhello.so.1
ln -s libhello.so.1 libhello.so
编译参数解析
1)-shared 该选项指定生成动态链接库,不用该标识外部程序无法链接;
2)-fPIC 表示编译为位置独立的代码,不用此选项编译后的代码是位置相关的,所以动态载入时通过代码拷贝的方式来满足不同进程需要,而不能达到真正的代码段共享的目的;
3)-L. 表示要链接的库在当前的目录,也可以指定为其它的目录;
4)-ltest 编译器查找动态库时有隐含的命名规则,前面加lib,后面加.so来确定库;
5)LD_LIBRARY_PATH 指示动态链接器可以装载的动态库路径;
6)如果有root权限,可以修改/etc/ld.so.conf文件,然后调用/sbin/ldconfig;
静态库的搜索路径:
1)ld会找GCC命令中的参数-L中指定的路径;
2)找gcc环境变量LIBRARY_PATH中的环境变量指定的路径;
3)找/lib /usr/lib /usr/local/lib路径;
动态库的搜索路径:
1)编译目标代码时指定的动态库搜索路径-L路径;
2)环境变量LD_LIBRARY_PATH中指定的路径;
3)配置文件/etc/ld.so.conf中指定的动态库搜索路径;
4)默认的动态库搜索路径/lib,/usr/lib
4. FAQ
SELinux权限问题
[root@localhost 20090505]# ./hello
./hello: error while loading shared libraries: /usr/lib/libmyhello.so: cannot restore segment prot after reloc: Permission denied
这是由于SELinux造成的,解决办法是使用chcon命令或者禁用SELinux:
1)使用chcon命令
# chcon -t texrel_shlib_t /usr/local/rsi/idl_6.1/bin/bin.linux.x86/*.so
# chcon -t texrel_shlib_t /usr/lib/libmyhello.so
2)禁用SELinux
修改/etc/sysconfig/selinux文件中的内容为SELINUX=disable,重启计算机。
GCC版本不兼容
在GCC4.5.1(Feroda 11)上编译的动态库和静态库无法在GCC4.1.2链接通过,反之亦然。
人创造奇迹常常是在瞬间,