原文网址: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. hdu4347The Closest M Points kdtree

    kdtree讲解: https://blog.csdn.net/qing101hua/article/details/53228668 https://blog.csdn.net/acdreamers ...

  2. macOS和常用命令

    macOS 常用命令 1. 显示“任何来源”选项 sudo spctl --master-disable 2. 阻止屏保和睡眠 caffeinate -t 3600 这是一个BSD命令.-t可选,按C ...

  3. python报错:TypeError: 'int' object is not subscriptable

    检查一遍报错的所在行,此报错一般是在整数上加了下标: 比如:   a = 4   c=a[2] 报错:line 2, in <module>    c=a[2] TypeError: 'i ...

  4. JAVA经典总结

    Java经典实例(第二版) 1. 获取环境变量 Java代码 1. System.getenv("PATH"); 2. System.getenv("JAVA_HOME& ...

  5. leetcode 559. Maximum Depth of N-ary Tree

    Given a n-ary tree, find its maximum depth. The maximum depth is the number of nodes along the longe ...

  6. 1.spring cloud eureka server配置

    IDEA版本 2017.2.5 JDK 1.8 红色加粗内容为修改部分 1.创建一个新项目 2.选择eureka依赖 3.版本选择(重要)并且更新依赖 <?xml version="1 ...

  7. CF910B

    题解: dp f[i][j]表示i根a,j根b要多少 然后随便转移一下 代码: #include<bits/stdc++.h> using namespace std; ][],n,a,b ...

  8. Week11《java程序设计》作业总结

    Week11<java程序设计>作业总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 答: 2. 书面作业 本次PTA作业题集多线程 1. 源代码 ...

  9. SpringInAction--条件化的Bean

    学习了profile bean之后,发现有的时候bean还是有根据环境来选择的余地的,那么假设我们希望某个bean只有当另外某个特定的bean也声明了之后才会创建.我们还可能要求只有某个特定的环境变量 ...

  10. L151

    In Toothy Prequel, Piranha-Like Fish Menaced Jurassic Seas You can call it a prehistoric prequel.Sci ...