linux 静态库和共享库

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;  
}  

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

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

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

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

敲入如下命令:

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

敲命令的时候要记得将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

后,再执行./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> dlfcn.h : Linux动态库的显式调用

函数

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

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

dlerror
函数定义:

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

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

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

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

编译参数 gcc -fPIC -shared

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

gcc -rdynamic -o main main.c -ldl

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值