静态库(.a)与动态库(.so)的简明介绍
静态库(.a)与动态库(.so)的简明介绍
gcc有很多关于静态库,动态库的选项如-l,-L,-fPIC,-shared -Wl,-soname,看着很复杂容易混淆,其实静态库和动态库都是应需而生,只要有了一个线索都很容易理解。
普通编译
假设有三个文件(后面均使用这个例子):
// mod1.c
#include <stdio.h>
void print_mod1(){
printf("%s\n",__func__);
}
// mod2.c
#include <stdio.h>
void print_mod2(){
printf("%s\n",__func__);
}
//main.c
int main(){
print_mod1();
print_mod2();
return 0;
}
我们要想运行这个程序需要先编译mod1.c,mod2.c生成目标文件,然后目标文件与main.c结合完成编译:
$ gcc -c mod1.c mod2.c
$ gcc -o resultant main.c mod1.o mod2.o
$ ./resultant
print_mod1
print_mod2
使用静态库(-lname -Lpath)
如果mod再多一点就会出现体力劳动:
$ gcc -o resultant mod1.o mod2.o mod3.o mod4.o mod5.o ... mod1024.o
于是就引入了静态库的概念。静态库又叫归档文件,在linux下是*.a后缀的文件,本质上就是目标文件(*.o)的一个集合。
- 使用
ar -r命令可以将*.o打包为一个静态库
$ ar r libmod.a mod1.o mod2.o
- 使用
ar tv libmod.a查看归档里面有哪些目标文件:
$ ar tv libmod.a
rw-r--r-- 0/0 1544 Dec 31 16:00 1969 mod1.o
rw-r--r-- 0/0 1544 Dec 31 16:00 1969 mod2.o
- 使用
ar d libmod.a mod2.o删除一个不需要的目标文件
打包好后就可以用libmod.a代替一串目标文件了:
$ gcc -o resultant main.c libmod.a
最常用的链接静态库的方式是添加-lname选项。-lname会默认链接名为libname.a的静态库:
$ gcc -o resultant main.o -lmod
/usr/bin/ld: cannot find -lmod
collect2: error: ld returned 1 exit status
这里我们如果直接使用-lmod gcc会提示找不到libmod.a模块,因为gcc只会在标准路径如/usr/lib,/lib查找,解决方法一是把libmod.a放到标准路径,二是使用-Lpath选项。
$ gcc -o resultant main.c -L. -lmod
$ ./resultant
print_mod1
print_mod2
-Lpath把指定路径加入链接器搜索路径,这里我们把当前目录(.)加入,自然就能找到libmod.a了。
使用动态库(-fPIC -shared)
静态库优点是方便,缺点是每个程序都有一份目标文件的,很多程序会使用printf,如果每个程序都包含一份printf.o的实现,会非常浪费磁盘空间和宝贵内存页。还有如果要对静态库中某一个目标文件进行更新,那么应用程序就需要重新链接。
基于这些需求,动态库诞生了。
动态库需要位置独立的代码,所以不能使用前面的mod1.o,mod2.o,需要-fPIC选项重新编译:
$ gcc -c -fPIC mod1.c mod2.c
然后再组合成动态库:
$ gcc -shared -o libmod.so mod1.o mod2.o
最后使用这个动态库:
$ gcc -o resultant main.c libmod.so
$ ./resultant
./resultant: error while loading shared libraries: libmod.so: cannot open shared object file: No such file or directory
好了,不出所料,又出问题了。gcc提示加载动态库失败,找不到它。动态库的搜索顺序如下
- 编译目标代码时指定的动态库搜索路径;
- 环境变量LD_LIBRARY_PATH指定动态库搜索路径,它指定程序动态链接库文件搜索路径;export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:data/home/billchen/lib
- 配置文件/etc/ld.so.conf中指定的动态库搜索路径;
- 默认的动态库搜索路径/lib;
- 默认的动态库搜索路径/usr/lib。
这里简单起见,我们直接将libmod.so移动到/lib:
$ sudo mv libmod.so /lib
$ ./resultant
print_mod1
print_mod2
动态库别名(-Wl,-soname,xx)
这里再说说-Wl,-soname,该选择告知链接器一个动态库的别名
$ gcc -shared -Wl,-soname,libalias.so -o libmod.so mod1.o mod2.o
$ gcc -o resultant main.c libmod.so
上面命令使用libalias.so作为libmod.so的别名,再次运行resultant会提示找不到libalias.so错误而不是libmod.so,-soname别名引入一个中间层,好处是程序运行时可以使用和编译时不一样的兼容库。
静态库(.a)与动态库(.so)的简明介绍的更多相关文章
- [转]Linux下g++编译与使用静态库(.a)和动态库(.os) (+修正与解释)
在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,对应的静态库 ...
- 《CMake实践》笔记三:构建静态库(.a) 与 动态库(.so) 及 如何使用外部共享库和头文件
<CMake实践>笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE <CMake实践>笔记二:INSTALL/CMAKE_INSTALL_PREFIX &l ...
- 在Linux中创建静态库.a和动态库.so
转自:http://www.cnblogs.com/laojie4321/archive/2012/03/28/2421056.html 在Linux中创建静态库.a和动态库.so 我们通常把一些公用 ...
- windows动态库与Linux动态库
Linux动态库和windows动态库的目的是基本一致的,但由于操作系统的不同,他们在许多方面还是不尽相同.但是尽管有差异Linux动态库的windows动态库还是可以移植的,有一些规则以及经验是必须 ...
- Linux C 静态库(.a) 与 动态库(.so) 的详解
库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种. 一.静态库和动态库的区别 1.静态函数库 这类库的名字一般是libxxx.a:利用静态函数库编译成的文件比较 ...
- [付费视频]Delphi视频Android开发使用静态库(A)和动态库(SO)
关于本视频:前阵子接到一个委托,解决Delphi开发Android程序中串口通信的问题,厂家那边提供了c文件,需要翻译成delphi可用,翻译倒是比较简单.不过后来翻译读写ic卡单元的时候进行不下去了 ...
- Linux链接库二(动态库,静态库,库命名规则,建立个没有版本号的软连接文件)
http://www.cppblog.com/wolf/articles/74928.html http://www.cppblog.com/wolf/articles/77828.html http ...
- Linux链接库一(动态库,静态库,库放在什么路径下)
http://www.cppblog.com/wolf/articles/74928.html http://www.cppblog.com/wolf/articles/77828.html http ...
- C/C++ 关于生成静态库(lib)/动态库(dll)文件如何使用(基于windows基础篇)
1. 首先,如何制作一个静态库(lib)? 额, 对于静态库,我们知道,里头是不应该有Main函数,它只是一个配合文件.之所以称之为lib静态库,其实就是指,我们需要用到lib里头的函数时,我们才会去 ...
随机推荐
- Mybatis工具Generator
转自:http://www.cuiyongzhi.com/post/36.html MyBatis Generator(以下简称为MBG),可以逆向生成持久层的基本代码,而且mybatis的实现方案比 ...
- Delphi PDF
llPDFLib,TPDFDocument 2016开始开源. procedure TForm2.Button1Click(Sender: TObject); var lPdf : TPdfDocum ...
- Tornado 高并发源码分析之二---Tornado启动和请求处理流程
Tornado 服务器启动流程 因为Tornado 里使用了很多传类的方式,也就是delegate,之所以要这么做,其实和 iOS 开发那样,也很多的 delegate, 如此来实现高度解耦,但是比较 ...
- centos 中没有 ifcfg-eth0 配置文件的解决办法
用 CentOS-6.5-i386-LiveDVD.iso 镜像安装好CentOS 6.5系统后(已经把系统写入硬盘),发现ip在每次重启后都会还原,用ifconfig查看是有eth0网卡的(也有可能 ...
- 【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 3_Linear Algebra Review
Lecture3 Linear Algebra Review 线性代数回顾 3.1 矩阵和向量3.2 加法和标量乘法3.3 矩阵向量乘法3.4 矩阵乘法3.5 矩阵乘法的性质3.6 逆.转置 3. ...
- Ceph基本情况介绍
Ceph基本情况的介绍 Ceph是一个分布式存储软件. 它支持用3种方式存储数据,分别是:对象存储.块设备存储.分布式文件系统存储. Ceph最初的目标是做一个分布式文件系统,直到现在这个目标也不能算 ...
- Gym 101606 F-Flipping Coins(概率dp)
参考博客:http://www.cnblogs.com/kang000/p/8571071.html (这篇博客写的真的走心,ORZ) 题意有n个硬币排成一排,开始的时候所有的硬币都是正面朝下,你必 ...
- 使用GDB调试PHP代码,解决PHP代码死循环
最近在帮同事解决Swoole Server问题时,发现有1个worker进程一直处于R的状态,而且CPU耗时非常高.初步断定是PHP代码中发生死循环. 下面通过一段代码展示如何解决PHP死循环问题. ...
- 【摘自大型网站技术架构书】负载均衡时session如何共享
由于负载均衡服务器可能会将请求分发到集群任何一台服务器上,所以保证每次请求能够获得正确的session比单机时复杂. 集群环境下,session管理的主要几种手段 1.session复制 sessio ...
- CLR 显示实现事件 EventSet内部管理一个字典
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...