你知道linux 静态库和共享库?

嵌入式技术

1372人已加入

描述

1、静态库和共享库 

静态库和共享库(动态库),二者的不同点在于代码被载入的时刻不同。 

静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。 
共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。

静态链接库和动态链接库的区别在于,主程序在运行前,静态链接库的链接固定写入在程序中,而动态链接库则是在每次程序运行再加载链接。

2、库存在的意义 
库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。 
现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。 
共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。

3.静态库 
Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表 
Step 2.ar命令将很多.o转换成.a,成为静态库

静态链接库 libcool.a 遵从 GNU/Linux 规定的静态链接库命名规范,必须是”libyour_library_name.a”

动态库的后缀是.so,它由gcc加特定参数编译产生。 
4、动态库

在 GNU/Linux 中动态链接文件,必需通过链接器 ld 生成。假设我们有 hot.c other.c 等文件要生成动态链接库 libhot.so 。首先使用如下指令得到相应的 object 文件 hot.o 和 other.o 
gcc -fPIC -c hot.c 
gcc -fPIC -c other.c 
参数 -fPIC 指定生成的 object 文件为位置无关代码(position-independence code),只有 PIC 可以被用作生成动态链接库。然后使用如下指令得到动态库:

ld -Bshared -o libhot.so hot.o other.o 
或者可以使用编译器的ld wrapper: 
gcc -shared -o libhot.so hot.o other.o 
也可以使用编译器直接生成动态库: 
gcc -fPIC -shared -o libhot.so hot.c other.c 
这里选项 -shared 指示目标文件的类型是动态链接库,动态库的命名规范是”libyour_library_name.so”

linux操作系统中, 
1.和静态库类似,动态库文件也是一些目标文件(后缀名为.o)的集合体而已。 
2.动态库的后缀名是.so,对应于windows操作系统的后缀名为.dll的动态库。 
3.可以使用gcc命令来创建一个动态库文件。 
来看一个实例,和静态库的代码实际是一样的。先看看可以编译成库文件的源文件中的代码:

/* test.c */ int f() { return 3; }

1

2

3

4

5

代码非常简单。我们敲入下列命令:

gcc -c -fPIC test.cgcc -shared -fPIC -o libtest.so test.o

1

2

会在当前目录下生成一个libtest.so动态库文件。再看如何使用这个库。看如下代码:

/* app.c */ #include extern int f(); int main() { printf(“return value is %d ”,f()); return 0; }

1

2

3

4

5

6

7

8

敲入如下命令:

gcc –c app.cgcc -o app app.o -L. –ltest

1

2

敲命令的时候要记得将libtest.a文件和生成的app.o文件放在同一个目录(即当前目录)下。这样,敲入命令后,会在当前目录下生成一个名为app的可执行文件。但是当我们执行./app命令,来执行这个可执行文件时,却提示如下错误:

这就奇怪了,libtest.so文件明明就在当前目录下,为什么会提示找不到呢?  原来linux和windows的机制是不同的,它不会在当前目录下寻找动态连接库文件,它只会在标准路径下寻找。(The system searches only /lib and /usr/lib, by default.)。我们可以使用一个命令,使得操作系统去我们指定的路径下面去寻找。假设libtest.so文件所在的目录是/root/Desktop/aabb,那么执行命令

export LD_LIBRARY_PATH=/root/Desktop/aabb

1

后,再执行./app,我们发现,程序就正常运行了。

在加载动态链接库的时候,有可能会遇到加载不到的错误,原因在于系统默认加载的动态链接库路径里没有找到你的动态库,有三种解决方法:

1.在执行gcc main.c -L. -ltest -o main 前,执行 export LD_LIBRARY_PATH=$(pwd)

2.将其添加到/etc/ld.so.cache文件中。将你so所在的目录写到/etc/ld.so.conf文件里,然后执行ldconfig该命令会重建/etc/ld.so.cache文件。

3.将你的so放在/etc/ld.so.conf里的路径位置里。

Linux下的dlopen、dlsym、dlclose 相当于windows平台的LoadLibrary、GetProcAddress 、FreeLibrary,可以在运行时动态加载动态库,使用其中的导出函数。但是局限在于,这样仅仅能够导出全局函数,而不能导出类的方法。所以一般动态库导出C++类实现的功能时都会设计一大堆的全局函数来包装一下。  包含头文件:

#include dlfcn.h : Linux动态库的显式调用

1

函数

void * dlopen( const char * pathname, int mode );

1

函数描述:    在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。    mode:分为这两种    RTLD_LAZY 暂缓决定,等有需要时再解出符号    RTLD_NOW 立即决定,返回前解除所有未决定的符号。

dlerror  函数定义:

void*dlsym(void* handle,const char* symbol)

1

函数描述:  dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。  dlclose

dlopen以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程,dlerror返回出现的错误,dlsym通过句柄和连接符名称获取函数名或者变量名,dlclose来卸载打开的库。 dlopen打开模式如下:

RTLD_LAZY 暂缓决定,等有需要时再解出符号    RTLD_NOW 立即决定,返回前解除所有未决定的符号。  生产动态链接库

编译参数 gcc -fPIC -shared

使用so文件的编译参数  编译选项如下:

gcc -rdynamic -o main main.c -ldl

1

选项 -rdynamic 用来通知链接器将所有符号添加到动态符号表中  (目的是能够通过使用 dlopen 来实现向后跟踪)比如日志系统,主程序里使用一套日志系统,dlopen方式打开的libso里无法使用。编译时加上这个参数,不需要增加任何代码就可以使代码通用。  使用-ldl选项指明生成的对象模块需要使用共享库



 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分