库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。 例如:libtest.so libtest.a。为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,但由于程序连接默认以.so为文件后缀名。所以为了使用这些 库,通常使用建立符号连接的方式。如: ln -s libtest.so.1.0 hello.so.1 ln -s libtest.so.1 hello.so 下面对比一下两者: 静态链接库:当要使用时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。 动态库而言:某个程序在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则 让其共享那一个拷贝;只有没有才链接载入。在程序运行的时候,被调用的动态链接库函数被安置在内存的某个地方,所有调用它的程序将指向这个代码段。因此, 这些代码必须使用相对地址,而不是绝对地址。在编译的时候,我们需要告诉编译器,这些对象文件是用来做动态链接库的,所以要用地址不无关代码 (Position Independent Code (PIC))。注意:linux下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。 下面就通过实际的例子来向大家演示一下,该怎样编译和使用静态和动态链接库,这里有一个头文件:lib_test.h,一个.c文件:lib_test.c: 1.编写库文件lib_test.c 2.编写一个头文件用于声明我们使用的函数lib_test.h 3.用gcc编绎该文件,可以使用任何合法的编绎参数 下面就用上面的文件生成和使用静态和动态链接库: 1)用gcc编绎该文件,可以使用任何合法的编绎参数 2) $ar crv libtest.a lib_test.o //生成静态库生成libtest.a 3) 在某些系统中还要为静态库生成一个内容表 $ranlib libtest.a 4) 使用静态链接库 $nm libtest.a //nm工具可以打印出库中的涉及到的所有符号,库既可以是静态的也可以是动态的。nm列出的符号有很多, 常见的有三种,一种是在库中被 调用,但并没有在库中定义(表明需要其他库支持),用U表示;一种是库中定义的函数,用T表示,这是最常见的;另外一种是所谓的"弱态” 符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。 $gcc -c -I/home/xxxxxxxx main.c //假设main.c要使用对应的静态库 $gcc -o main -L/home/xxxxxxxx main.o libtest.a 说明:这里的-I/home/xxxxxxxx和-L/home/xxxxxxxx 是通过-I和-L指定对应的头文件和库文件的路径,libtest.a就是要用的静态库。在main.c中要包含静态库 的头文件。 5)然后执行程序就可以看到成功了。#./main (二)动态链接库 可以依次使用下面的命令 1)$gcc -fPIC -o libtest.o -c lib_test.c 2)$gcc -shared -o libtest.so libtest.o 也可以直接使用一条命令gcc -fPIC -shared -o libtest.so lib_test.c 3)有两种方法使用动态链接库。 a)#gcc -o main main.c ./libtest.so b)先#cp ./libtest /usr/lib 然后gcc -o test test.c libtest.so这时要保证这个库所在目录包括再PATH 环境变量中。 4)然后执行程序就可以看到成功了。#./main 最后说一下库的路径问题,算是结个尾吧: 动态库的搜索路径搜索的先后顺序是: 1.编译目标代码时指定的动态库搜索路径; 2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径; 3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;//只需在在该文件中追加一行库所在的完整路径如"/root/test/conf/lib"即可,然后ldconfig是修改生效。 4.默认的动态库搜索路径/lib; 5.默认的动态库搜索路径/usr/lib。 |
|