Linux链接库使用

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链接通过,反之亦然。

人创造奇迹常常是在瞬间,

Linux链接库使用

相关文章:

你感兴趣的文章:

标签云: