2.2.9linux下的网络编程之动态链接库
参考资料
Linux网络编程
比较好的静态库和动态库博客
2.2.9生成动态链接库的一些步骤
先给出一些命令的介绍和说明
文件
-
main.c
-
string.c
一些链接过程的回顾
单个文件
gcc filename.c
没有指定生成文件的名字,所以生成a.out.
编译生成目标文件的话
4 指定生成的目标文件的名字
-c 生成目标文件
gcc -c -o test.o hello.c
目标文件是多文件组织的基本单元,可以重定位,即确定在一个大的程序组织中的地址。
5多文件编译
源文件string.c
/*string.c*/
#define ENDSTRING '\0' /*定义字符串*/
int StrLen(char *string)
{
int len = 0;
while(*string++ != ENDSTRING) /*当*string的值为'\0'时,停止计算*/
len++;
return len; /*返回此值*/
}
源文件main.c
/*main.c*/
#include <stdio.h>
extern int StrLen(char* str); /*声明Strlen函数*/
int main(void)
{
char src[]="Hello Dymatic"; /*字符串*/
printf("string length is:%d\n",StrLen(src)); /*计算src的长度,将结果 打印出来*/
return 0;
}
编译运行
gcc -o test string.c main.c
执行编译出来的可执行文件
./test
可以分解为如下过程
gcc -c string.c main.c
gcc -o test string.o main.o
6查看预处理
-E会告诉编译器进行预编译操作,
输出中间文件
会引入头文件,替换宏定义
gcc -E string.c
gcc -o string.i -E string.c
7编译成汇编语言
gcc -S string.c
8生成和使用静态链接库
静态库是obj文件的集合,以.a为后缀,由程序ar(archive)生成,不用重新编译程序库代码的情况下,重新链接,缺点应该是比较大,会导致生成的程序很大。
- 生成静态链接库
> ar rcs libMyTest.a *.o # 将所有.o文件打包为静态库,r将文件插入静态库中,c创建静态库,不管库是否存在,s写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。
> mv libMyTest.a ../lib #将静态库文件放置lib文件夹下
> nm libMyTest.a #查看库中包含的函数等信息
ar -rcs libstr.a string.o
- 使用静态链接库
gcc -o test main.c libstr.a
- 使用 "-l 库名"库名是不包含函数库和扩展名的字符串,例如编译main.c链接静态库libstr.a
省去了前缀lib,和后缀.a
gcc -o test main.c -lstr
执行的说明
默认路径
-L参数指定到哪个附加路径下面去寻找共享库
gcc -o test main.c -L ./-lstr
9 生成动态链接库26
- 生成动态链接库
-shared是制作动态库的关键字
gcc -shared -fPCI -o libstr.so string.c
版本的绑定,建立软连接
g++ -shared -Wl,-soname libstr.so -o libstr.so.1 string.c
-Wl 告诉编译器将后面的参数传递到连接器。而 -soname 指定了 共享库的 soname这个soname的存在是为了兼容方便。
比如:
有一个程序ap1,以及一个库libtest.so.1
ap1启动的时候需要libtest.so.1
如果链接的时候直接把libtest.so.1传给了ap1,那么将来库升级为libtest.so.2的时候,ap1仍然只能使用libtest.so.1的代码,并不能得到升级的好处。而如果指定了soname为libtest.so,那么ap1启动的时候将查找的就是libtest.so而不是其在被链接时实际使用的库libtest.so.1这个文件名。在开始时我们建立一个链接:ln -sf libtest.so.1 libtest.so
而在库升级后,我们重新:ln -sf libtest.so.2 libtest.so即可,这样ap1不需要任何变动就能享受升级后的库的特性了。而libtest.so.1,libtest.so.2可以同时存在于系统内,不必非得把libtest.so.2的名字改成libtest.so.1
- 动态链接库的配置
动态链接库不能随意使用,要在运行的程序中使用,指定系统的动态链接库搜索路径。系统配置文件/etc/ls.so.conf
是动态链接库搜索路径的配置文件
查看内容
cat /etc/ld.so.conf
3. 动态链接库的管理
idconfig在系统默认搜索路径和动态链接库配置问及那中所列出的目录里搜索动态链接库,搜索后见结果写入缓存文件/etc/ld.so.cache
-
命令和参数
- 常用的命令组合
-
列出缓存文件的动态库列表 ldconfig -p
-
ldconfig -v 将ldconfig 扫描的信息输出到终端
指定扫描的 目录
添加用户的lib
-
- 使用动态链接库
使用 -l 库名的方式下面的命令将源文件main.c编译成可执行文件test,并链接库文件libstr.a或者libstr.so
- 常用的命令组合
gcc -o test main.c -L ./ -lstr
可能遇到的问题和解决方法
没有找到动态链接库造成的。
编译时链接和动态链接的注册有区别。
export LD_LIBRART_PATH=/example/ex02: $LD_LIBRARY_PATH
使用ld-Linux.so.2来加载程序
使用链接命令来链接 ,动态库路径和程序名
10动态加载库
动态加载库和动态链接库不同,可以使用程序控制
-
打开动态库的函数dlopen()
-
获得函数指针dlsym()
获得动态链接库中指定函数的指针,使用指针进行操作
handle是文件句柄,是第一个函数的返回值。
-
使用动态加载库的例子
/*动态加载库示例*/
#include <dlfcn.h>/*动态加载库库头*/
#include <stdio.h>
int main(void)
{
char src[]="Hello Dymatic"; /*要计算的字符串*/
int (*pStrLenFun)(char *str); /*函数指针*/
void *phandle = NULL; /*库句柄*/
char *perr = NULL; /*错误信息指针*/
phandle = dlopen("./libstr.so", RTLD_LAZY); /*打开libstr.so动态链接库*/
/*判断是否正确打开*/
if(!phandle) /*打开错误*/
{
printf("Failed Load library!\n"); /*打印库不能加载信息*/
}
perr = dlerror(); /*读取错误值*/
if(perr != NULL) /*存在错误*/
{
printf("%s\n",perr);
return 0; /*正常返回*/
}
pStrLenFun = dlsym(phandle, "StrLen"); /*获得函数StrLen的地址*/
perr = dlerror(); /*读取错误信息*/
if(perr != NULL) /*存在错误*/
{
printf("%s\n",perr); /*打印错误函数获得的错误信息*/
return 0; /*返回*/
}
printf("the string length is: %d\n",pStrLenFun(src)); /*调用函数pStrLenFunc计算字符串的长度*/
dlclose(phandle); /*关闭动态加载库*/
return 0;
}
说明 -ldl就是对 libdl.so 的使用
就是包含这四个函数的库
- dlopen//打开一个动态库
- dlsym//在打开的动态库里找一个函数
- dlclose//关闭动态库
- dlerror//返回错误
11 GCC常用选项
头文件路径
加载库路径
警告信息
调试
-
-DMACRO 选项
-
GCC的常用选项和含义
比较多,以后总结