原文网址:http://blog.csdn.net/heyabo/article/details/11688517

申明: 正如题如示,本篇讲的是Linux下是静态库与共享库,而Window下的动态链接库详细情况可见这篇文章:windows动态链接库 DLL 浅析。虽然原理,思想差不多,但是细节却各有不同。

一、静态库

 
1、概念:静态库指将所有相关的目标文件打包成为一个单独的文件-即静态库文件,以.a结尾。静态库可作为链接器的输入,链接器会将程序中使用的到函数的代码从库文件中拷贝到应用程序中。一旦链接完成,在执行程序的时候就不需要静态库了
 
注1:由于每个使用静态库的应用程序都需要拷贝所用函数的代码,所以静态链接的文件会比较大。
注2:在Unix系统中,静态库以一种称为存档(archive)的特殊文件格式存放在磁盘中。存档文件是一组连接起来的可重定位目标文件的集合,有一个头部用来描述每个成员目标文件的大小和位置(存档文件名由后缀.a标识)。
 
2、创建与应用
 
假设我们想在一个叫做libvector.a的静态库中提供以下向量函数:
  1. // addvec.c
  2. void addvec(int* x, int* y, int*z, int n)
  3. {
  4. int i=0;
  5. for(; i< n;++i)
  6. z[i] = x[i] + y[i];
  7. }
  1. // multvec.c
  2. void multvec(int*x, int* y, int*  z, int n)
  3. {
  4. int i = 0;
  5. for(; i < n; ++i)
  6. z[i] = x[i] * y[i];
  7. }
使用AR工具创建静态库文件:
 
为了使用这个库,编写一个应用(其调用addvec库中的函数):
 
  1. /* main2.c */
  2. #include <stdio.h>
  3. int x[2] = {1, 2};
  4. int y[2] = {3, 4};
  5. int z[2]={0};
  6. int main()
  7. {
  8. addvec(x, y, z, 2);
  9. printf("z = [%d %d]\n", z[0], z[1]);
  10. return 0;
  11. }
编译-链接-运行程序:
 
注1-static 参数告诉编译器驱动程序,链接器应该构建一个完全的可执行目标文件,它可以加载到存储器并运行,在加载时无需进一步的链接 -即一次性静态链接完毕,不允许存在动态链接
注2:当链接器运行时,它判定addvec.o定义的addvec符号是被main2.o引用的,所以它拷贝addvec.o到可执行文件。因为程序中没有引用任何由multvec.o定义的符号,所以链接器就不会拷贝这个模块到可执行文件。同时,链接器还会拷贝libc.a中的pirintf.o模块,以及许多C运行时系统中的其他模块。链接器完整的行为可如下图所示:
 
二、共享库
 
1、概念:共享库是一个目标模块(以.so后缀表示),在运行时,可以加载到任意的存储器地址,并和一个在存储器中的程序链接起来,这个过程称为动态链接,是由一个叫做动态链接器的程序来执行的。
 
2、分类:根据加载和链接共享库的时机又可分为:A)应用程序自身加载时动态链接和加载共享库;B)应用程序运行过程中动态链接和加载共享库两种情况。
 
2-A:应用程序自身加载时动态链接和加载共享库
 
2-A.1 基本思路是:当创建可执行文件时,静态执行一些链接(共享库的重定位和符号表信息,而非代码和数据),然后在应用程序加载时,动态完成链接过程。
 
2-A.2 创建与应用
 
创建类似于静态库的创建,假设我们现在想在一个叫做libvector.so的共享库库中提供以下addvec和multvec函数:
下面使用-shared选项来指示链接器创建一个共享的目标文件(即共享库),链接并运行程序:
 
注1-fPIC选项指示编译器生成与位置无关的代码
其动态链接过程可如下图所示:
 
注2:在可执行文件p2中没有拷贝任何libvector.so真正的代码和数据节,而是由链接器拷贝了一些重定位和符号表信息,它们使得运行时动态链接器可以解析libvector.so中代码和数据的引用,重定位完成链接任务。其中需要重定位的有:
  • 1)重定位libc.so的文本和数据到某个存储器段;
  • 2)重定位libvector.so的文本和数据到另一个存储器段;
  • 3)重定位p2中所有对libc.so和libvector.so定义的符号的引用。
最后链接器将控制传递给应用程序。从这个时刻开始,共享库的位置就固定了,并在在程序的执行过程中都不会再改变
 
2-B:应用程序运行过程中动态链接和加载共享库
 
2-B.1 概念:与A情况不同,此情况下:应用程序在运行过程中要求动态链接器加载和链接任意共享库,而无需编译时链接那些库到应用中。
 
2-B.2 应用实例
Linux系统为应用程序在运行过程中加载和链接共享库提供了一组API:
  1. #include<dlfcn.h>
  2. /* 加载和链接共享库 filename
  3. filename:共享库的名字
  4. flag有:RTLD_LAZY, RTLD_NOW,二者均可以和RTLD_GLOBAL表示取或
  5. */
  6. void *dlopen(const char *filename, int flag); // 若成功则返回执行句柄的指针,否则返回NULL
  7. /*根据共享库操作句柄与符号,返回符号对应的地址
  8. handle:共享库操作句柄
  9. symbol:需要引用的符号名字
  10. */
  11. void *dlsym(void *handle, char *symbol); // 若成功则返回执行符号的指针(即地址),若出错则返回NULL
  12. /* 如果没有程序正在使用这个共享库,卸载该共享库 */
  13. int dlclose(void *handle); // 若卸载成功,则返回0,否则返回-1
  14. /* 捕捉最近发生的错误 */
  15. const char *dlerror(void); // 若前面对dlopen,dlsym或dlclose调用失败,则返回错误消息,否则返回NULL

例子

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <dlfcn.h>
  4. int x[2] = {1, 2};
  5. int y[2] = {3, 4};
  6. int z[2] ={0};
  7. int main()
  8. {
  9. void *handle;
  10. void (*addvec)(int *, int *, int *,int);
  11. char *error;
  12. handle = dlopen("./libvector.so", RTLD_LAZY);
  13. if(!handle){
  14. fprintf(stderr, "%s\n", dlerror());
  15. exit(1);
  16. }
  17. addvec = dlsym(handle, "addvec");
  18. if((error = dlerror()) != NULL){
  19. fprintf(stderr, "%s\n", dlerror());
  20. exit(1);
  21. }
  22. addvec(x, y, z, 2);
  23. printf("z = [%d %d]\n", z[0], z[1]);
  24. if(dlclose(handle) < 0){
  25. fprintf(stderr, "%s\n", dlerror());
  26. exit(1);
  27. }
  28. return 0;
  29. }

运行结果:-ldl参数:表示生成的对象模块需要用到共享库

Referebces:

1.《深入理解计算机系统》第7章:链接 P448-P479

2. 静态库、共享库、动态库的创建和使用 :http://bbs.chinaunix.net/thread-2037617-1-1.html

3. Linux 动态库剖析:http://www.ibm.com/developerworks/cn/linux/l-dynamic-libraries/

4. dlopen: http://baike.baidu.com/link?url=VswI42A-IxFuF5SelbJxDREXuY0BvYWHEdcCYozSNH93ark0nTMi4YdhHrvt-bIo2_F-swU2onuYMNwXeUGVMq

【转】Linux 静态库与共享库的使用的更多相关文章

  1. Linux 静态库与共享库的使用

    申明: 正如题如示,本篇讲的是Linux下是静态库与共享库,而Window下的动态链接库详细情况可见这篇文章:windows动态链接库 DLL 浅析.虽然原理,思想差不多,但是细节却各有不同. 一.静 ...

  2. linux下的静态库和共享库

    转载&&增加:      我们在编写一个C语言程序的时候,经常会遇到好多重复或常用的部分,如果每次都重新编写固然是可以的,不过那样会大大降低工作效率,并且影响代码的可读性,更不利于后期 ...

  3. Linux下库的制作(静态库与共享库)

    库中实际上就是已编译好的函数代码,可以被程序直接调用. Linux下的库一般的位置在/lib或者/usr/lib中 静态库 静态库是复制拷贝到调用函数中的,函数运行的时候不再需要静态库,因为静态库是在 ...

  4. 第二课 GCC入门之静态库以及共享库

    序言: 前面一课讲了gcc的简单入门,包括gcc编译步骤:预处理:编译:汇编:链接.今天这节课就来讲下linux的库也欢迎大家吐糟共同学习. 原理: linux系统中分为2种库:静态库和共享库.静态库 ...

  5. Linux下Qt创建共享库与链接共享库详解

    随着程序写的逐渐变多,或多或少的我们都会使用别人写好的库:或者我们不想让别人看到我们的一些核心程序,可以将核心程序封装成库.本次和大家分享的是在Ubuntu下使用Qt生成共享库以及在Qt中链接共享库的 ...

  6. Linux静态库和共享库

    1.什么是静态库静态库类似windows中的静态lib 关于windows中的静态lib,可参考 Windows动态链接库DLL 特点:包含函数代码声明和实现,链接后所有代码都嵌入到宿主程序中. 只在 ...

  7. Linux静态库和共享库【转】

    转自:http://www.cnblogs.com/zlcxbb/p/6806269.html 1.什么是静态库 静态库类似windows中的静态lib 关于windows中的静态lib,可参考 Wi ...

  8. Linux命令(十二)制作静态库和共享库

    1. 静态库 静态库文件命名:libxxxx.a 1.1 步骤: ar rcs libCalc.a *.o 1.2 用nm查看文件内容 1.3 发布并使用 gcc main.c -o mycpp.ou ...

  9. gcc创建静态库和共享库

    静态库和动态(共享)库静态库:编译程序在编译使用库提供的功能代码的程序时将代码复制到该程序然后编译成可执行程序,这种库成为静态库共享库:共享库比静态库的处理方式更加灵活,因而其产生的可执行文件更小,其 ...

随机推荐

  1. 使用python编写微信跳一跳的自动脚本

    实现思路: 调用adb命令,截图 寻找小小人的底部中心点role(从下到上扫描,直到找到小小人相同像素的点,至于小小人像素点rgb是什么,可以使用photoshop查看) 寻找棋盘最高点top,然后寻 ...

  2. UVA-11294 Wedding (2-SAT)

    题目大意:一张长桌,n对夫妻,编号为0~n,这些人要坐在长桌两侧,每对夫妻不能坐在同一侧.其中,有2*m个人相互讨厌,编号为0的夫妻中的妻子不愿意让对面那一侧中有两个相互吵过架的人,找一种排座位方案. ...

  3. 打开Eclipse提示“The default workspace “xxxx” is in use or cannot be created Please choose a different one“

    原因:出现这种情况一般是workspace的配置文件中出现了.lock文件(workspace/.metadata/.lock),锁定了workspace.把.lock文件删除即可. 如果该文件不能删 ...

  4. centos7 rabbitmq 安装

    http://www.rabbitmq.com/install-rpm.html Overview rabbitmq-server is included in Fedora. However, th ...

  5. vue中element 的上传功能

    element 的上传功能 最近有个需求,需要在上传文件前,可以进行弹窗控制是否上传upload 看完文档后,感觉有两种思路可以实现 基于before-upload :上传文件之前的钩子,参数为上传的 ...

  6. Prism 4 文档 ---第3章 管理组件间的依赖关系

     基于Prism类库的应用程序可能是由多个松耦合的类型和服务组成的复杂应用程序,他们需要根据用户的动作发出内容和接收通知进行互动,由于他们是松耦合的,他们需要一种方式来互动和交流来传递业务功能的需求. ...

  7. ES的Zen发现机制

    ES的Zen发现机制 Zen发现机制是ElasticSearch默认的发现模块.它提供的是单播发现,但是可被拓展为支持云环境下或者其他形式的发现机制.zen 发现模块集成了其他模块,如在发现期间,节点 ...

  8. DRF中序列化器定义及使用

    首先需要明白序列化和反序列化的定义及作用: 序列化是将程序语言转换为JSON/XML; 反序列化是将JSON/XML转换为程序语言; 对应到Django中,序列化即把模型对象转换为字典形式, 在返回给 ...

  9. Oracle解决中文乱码

    原因 经过一番查证,发现问题的源头不是出现在PLSQL上,而是出现在我们的Oracle上,由于我们的Oracle数据库里的字符集不支持中文导致的,既然知道了原因,就好办了,我们就配置我们的Oracle ...

  10. online learning,batch learning&批量梯度下降,随机梯度下降

    以上几个概念之前没有完全弄清其含义及区别,容易混淆概念,在本文浅析一下: 一.online learning vs batch learning online learning强调的是学习是实时的,流 ...