一、动态库的编译



1. 什么是动态库(共享库)


动态库是可以执行的,静态库不能执行


但动态库没有main,不能独立执行


动态库不会连接成程序的一部分


程序执行时,必须需要动态库文件



2. 工具


ldd   查看程序需要调用的动态库


ldd   只能查看可执行文件(共享库文件或elf文件)


readelf -h (-h表示查看执行文件头)


nm (查看库中的函数符号)


3. 动态库的编译


3.1编译


-c -f pic(可选) (-f 指定文件格式pic 位置无关代码)


3.2 连接


-shared


 


编译:gcc -c -fpic iotool.c


gcc -c -fpic graphic.c


(非标准)gcc -shared -odemo3.so iotool.o graphic.o


(标准)gcc -shared -olibdemo4.so iotool.o graphic.o



4. 使用动态库


gcc 代码文件名 动态库文件名


gcc 代码文件名 -l库名 -L动态库所在的路径


gcc main.c -ldemo4 -L. -o main


 


标准命名规则:


lib库名.so


lib库名.a


 


问题:


4.1 执行程序怎么加载动态库?


4.2 动态库没有作为执行程序的一部分,为什么连接需要制定动态库及目录?


因为连接器需要确认函数在动态库中的位置


动态库的加载:


1. 找到动态库


2. 加载动态库到内存(系统实现)


3. 映射到用户的内存空间(系统实现)


动态库查找规则:


/lib


/user/lib


LD_LIBRARY_PATH环境变量指定的路径中找


设置当前路径为环境变量:


export LD_LIBRARY_PATH=.:~:..:~Walle


缓冲机制:


系统把lib:/user/lib:LD_LIBRARY_PATH里的文件加载到缓冲


/sbin/ldconfig -v 刷新缓冲so中的搜索库的路径


小练习:


输入两个数,计算两个数的和。


要求:输入与计算两个数的和封装成动态库调用



1)inputInt.c


#include <stdio.h>


int inputInt(const char* info){

   printf("%s\n",info);
   int r;
   scanf("%d",&r);
   return r;
}


2)add.c


int add(int a, int b){
  return a+b;
}


3)main.c


#include <stdio.h>


int main(){
   int a = inputInt("please input the first number");
   int b = inputInt("please input the second number");

   int result = add(a,b);

   printf("the sum of two number is %d\n",result);
   return 0;

}


编译:


[fedora@localhost day02_r3]$ gcc -fpic -c inputInt.c 
[fedora@localhost day02_r3]$ gcc -fpic -c add.c 



连接:


[fedora@localhost day02_r3]$ gcc -shared -o libdemo1.so inputInt.o add.o



使用:


[fedora@localhost day02_r3]$ gcc main.c -omain -ldemo1 -L.



这时候,系统有可能还无法找到动态库的位置。。。


在命令行中输入ldd main,这时候你可能看到以下信息:


[fedora@localhost day02_r3]$ ldd main
linux-gate.so.1 =>  (0xb77a2000)
libdemo1.so => not found     //这一样信息表示系统无法找到你的动态库
libc.so.6 => /lib/libc.so.6 (0x4e092000)
/lib/ld-linux.so.2 (0x4e070000)




这时候需要进行以下操作,告诉系统应该去那里寻找动态库


[fedora@localhost day02_r3]$ export LD_LIBRARY_PATH=.:..:~:~fedora



这时候,再输入ldd main 查看用户执行程序main需要哪些动态库时,我们可以看到以下信息:
[fedora@localhost day02_r3]$ ldd main
linux-gate.so.1 =>  (0xb779e000)
libdemo1.so => ./libdemo1.so (0xb779b000)  //这时就可以找到动态库了,这里找的是当前目录下 libdemo1.so
libc.so.6 => /lib/libc.so.6 (0x4e092000)
/lib/ld-linux.so.2 (0x4e070000)





-----------------------------------动态库的基本使用------------------------------------------------------------


1、编译


gcc -fpic -c inputInt.c 



2、连接


gcc -shared -o libdemo1.so inputInt.o add.o



3、使用


gcc main.c -omain -ldemo1 -L.



4、告诉系统去哪里找动态库


export LD_LIBRARY_PATH=.:..:~:~fedora