Linux下的动态库和静态库详解
动态库和静态库
文章目录
- 动态库和静态库
- 静态库与动态库的概念
- 理解动静态库
- 如何打包动静态库与如何使用动静态库
- 如何制作打包动态库
为什么我们要使用别人(一般是顶尖的工程师写的)的代码?
为了开发效率和鲁棒性(健壮性)
如何使用别人的功能?
1、库 2、开源代码 3、基本的网络功能调用(各自网络接口,语音识别)
库一般分为动态库和静态库,动态库一般的命名为libc.so,静态库一般的命名为libc.a,去掉前缀lib,去掉.之后的内容,剩下的就是库的名字,这里就是c库,生成可执行程序的方式有两种:动态链接和静态链接
#include<stdio.h>
int main()
{printf("hello world!\n");return 0;
}
ldd 可执行程序名字:查看可执行程序的动态链接关系
在linux当中,默认情况下形成的可执行程序是动态链接的,可以看到这里是.so为后缀的
下面我们举个例子来解释一下动态链接和静态链接:
比如你在宿舍写作业,写到某个题突然不会了,学校旁边有个网吧,于是你就去网吧去查找资料解决问题,解决完了然后回到宿舍继续完成作用,还有一种方法就是你告诉你爸让给你买台电脑,你在宿舍有台电脑,于是你就不需要再去网吧去使用电脑去查阅资料,直接在自己买的电脑上面查找资料即可,前面说的那种方法类似于动态链接,后面的那种方法叫做静态链接
当调用库频率增加时或者在上面的例子中说去网吧查阅资料频繁时,就变得很麻烦,就和上面的例子一样我们自己买个电脑,这样就省事了不少。相对应的把库中的我的可执行程序中所需要使用的二进制代码,拷贝进我的可执行程序当中,这就叫做静态链接。
如果想使用静态链接,那就在gcc后面+static选项:一般,为了更好的支持开发,第三方库或者语言库,必须提供两个库,一个叫做静态库,一个叫动态库,方便程序员根据需要进行bin的生成
动态链接的特点:体积小,节省资源(磁盘,内存),但是一旦库丢失,bin不可执行
静态链接的特点:体积大,浪费资源(磁盘,内存),不依赖库,库丢失不影响可执行程序
静态库与动态库的概念
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
- 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
- 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
- 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
- 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
理解动静态库
如何打包动静态库与如何使用动静态库
不想将源代码暴露给别人,就需要打包动静态库,下面我们来看如何打包动静态库:
我们首先写好自己想要打包的程序代码:
add.c
#include"add.h"
int myadd(int x,int y)
{return x+y;
}
add.h
#pragma once
#include<stdio.h>
int myadd(int x,int y);
sub.c
#include"sub.h"
int mysub(int x,int y)
{return x-y;
}
sub.h
#pragma once
#include<stdio.h>
int mysub(int x,int y);
我们想让别人能使用我的库,前提是别人需要首先知道你的库能给我提供什么方法,通过头文件体现,然后将源文件编译生成目标文件:
gcc -c add.c
生成.o文件,这个.o文件可以被别人链接
gcc -c sub.c
然后使用ar -rc命令生成静态库:
ar -rc libmymath.a add.o sub.o
我们只需要将头文件和这个刚生成的库文件给别人就好了,别人就可以用该库,形成自己的可执行程序
我们将头文件和这个刚生成的库文件都放进lib目录下,自己写个程序使用它:
#include<stdio.h>
#include"Add.h"
#include"sub.h"
int main()
{printf("%d\n",myadd(10,20));printf("%d\n",mysub(10,20));return 0;
}
这里会报错,找不到:
因为去当前路径或者默认路径(/usr/include)下找头文件,所以需要告诉gcc在指定路径下去找一下头文件:
-I选项:
gcc test.c -o mytest -I ./lib
我们发现还会有问题:
我们需要告诉gcc除了默认路径(/lib64/libc)以及当前路径之外,在指定的路径下也找一下库文件:
-L(大写)选项:
gcc test.c -o mytest -I ./lib -L ./lib -lmymath
-l(小写)库名称:具体你要链接哪一个库
可以看到成功执行了
为什么C语言在编译的时候,从来没有明显的使用过-I -L -l等选项呢?
- 库文件和头文件在默认路径下gcc能找到
- gcc编译C代码,默认就应该链接libc
如果我们也不想使用这些选项呢?
头文件库文件分别拷贝到默认路径下,这个过程叫做库的安装,对于第三方库例如我们自己写的,一般也要带上-lname
如何制作打包动态库
生成动态库:
Makefile的编写
libmymath.so add.o sub.ogcc -shared -o $@ $^
add.o:add.cgcc -fPIC -c $^
sub.o:sub.cgcc -fPIC -c $^
gcc选项 -fPIC:产生与位置无关码
在进程地址空间中有共享区,一般动态库的代码是映射在共享区的,我们将库代码加载到内存,通过页表映射到进程地址空间的共享区,当其他程序想要相同的库代码时,可以通过页表映射到内存中相同库代码的部分,这样就大大减少了空间的使用情况,库有可能加载到物理内存的任意位置,也可能被映射到进程地址空间中共享区的任意区域,所以必须保证库当中的代码怎么执行都不会错,为了保证这个库当中的代码地址不随着加载到内存的位置发生变化而变化,需要告诉gcc,我们进行fPIC选项产生与位置无关码进行编译
我们通过静态库的那套方式进行编译链接:
gcc test.c -o mytest -I ./dy_lib -L ./dy_lib -lmymath
我们运行可执行程序,发现无法正常运行:
此时和编译器gcc还有关系吗?毫无关系,是运行时出现的问题,属于运行问题,也要能够让系统帮我们找到运行时需要使用的动态库。
为什么之前动态链接的其他程序可以直接运行呢?因为库可以找到
环境变量LD_LIBRARY_PATH,需要将库的路径导入到环境变量LD_LIBRARY_PATH中:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/whb/101/lesson18/dy_lib/test/lib/
可以看到此时就可以正常执行了
Linux下的动态库和静态库详解相关推荐
- PHP编译为静态库,Linux下将Tinyxml编译为静态库
转载请注明来源:Linux下将Tinyxml编译为静态库 一个应用需要在linux服务器上运行,不能保证每个服务器都有应用依赖的库,又懒得每个服务器都去安装下,也不太现实,于是就将应用所用到的库全部编 ...
- Linux下的tar归档及解压缩功能详解
Linux下的tar归档及解压缩功能详解 一.Linux下解压缩工具 二.gzip工具的使用方法 三.其他解压缩工具 一.Linux下解压缩工具 二.gzip工具的使用方法 三.其他解压缩工具 一.L ...
- linux为什么用tar压缩,linux下tar压缩和解压命令用法详解
linux下tar压缩和解压命令用法详解 2017-03-25 14:06 分享人:老牛 将/usr/local/test目录下所有文件仅打包,不压缩到 /usr/local/auto_bak/目下 ...
- linux 子域dns,linux下搭建DNS子域及相关授权详解
linux下搭建DNS子域及相关授权详解forward功能是本地无法解析的域名,转发给指定DNS服务器 forward only; 所有无法解析的域名,都转发给指定DNS服务器,必须有解析结果 for ...
- linux添加nginx,linux下安装Nginx1.16.0的教程详解
因为最近在倒腾linux,想安装新版本的nginx,找了一圈教程没有找到对应的教程,在稍微倒腾了一会之后终于成功的安装了最新版. 服务器环境为centos,接下来是详细步骤: 安装必要依赖插件 ? 创 ...
- Linux环境下怎么使用pip,linux下pip的安装步骤及使用详解
linux下pip的安装步骤及使用详解 pip类似RedHat里面的yum,安装软件非常方便.下面话不多说,来看看详细的介绍: pip下载:# wget "https://pypi.pyth ...
- linux nginx编译详解,Linux下nginx编译安装教程和编译参数详解
这篇文章主要介绍了Linux下nginx编译安装教程和编译参数详解,需要的朋友可以参考下 一.必要软件准备 1.安装pcre 为了支持rewrite功能,我们需要安装pcre 复制代码 代码如下:# ...
- linux下搭建DNS子域及相关授权详解
linux下搭建DNS子域及相关授权详解 forward功能是本地无法解析的域名,转发给指定DNS服务器 forward only; 所有无法解析的域名,都转发给指定DNS服务器,必须有解析结果 fo ...
- linux下mysql数据库基础及客户端命令详解
linux下mysql数据库基础及客户端命令详解 1.mysql数据库存储引擎: SHOW ENGINES; #查看mysql支持的存储引擎 常见有如下两个存储引擎: MyISAM:每表三个文件: ...
- Linux下解析域名命令-dig 命令使用详解
Linux下解析域名除了使用nslookup之外,开可以使用dig命令来解析域名,dig命令可以得到更多的域名信息.dig 命令主要用来从 DNS 域名服务器查询主机地址信息.dig的全称是 (dom ...
最新文章
- nanodet学习笔记 tensorrt
- 《你的误区》《少有人走过的路》下载doc格式
- linux系统里常用的抓图工具,Linux系统下屏幕截图常用方法
- js改变select下拉框默认选择的option
- 从客户端(CourseIssueContent=P财务审计师岗位认证招生简章BR...)中检测到有潜在危险的 Request.Form 值。...
- ROS环境下跑orb-slam2 单目相机
- 聚合项目访问后台接口失败_聚合支付系统和免签支付系统对未来支付市场有哪些影响...
- 转:利用深度学习方法进行情感分析以及在海航舆情云平台的实践
- php抓取动态数据,php+ajax实现无刷新动态加载数据技术
- mysql text类型 使用方法_MySQL使用TEXT/BLOB类型的知识点详解
- 电大计算机理工英语19年秋季,国开电大理工英语1单元自测5形考任务答案
- 数学归纳法在数据结构与算法分析设计中的应用
- uni-app 开发跨平台应用前端框架
- iOS系统的设备怎么装两个微信?
- 懂得,是生命中最美的缘
- kobo glo刷安卓
- android 画图功能,Android实现简单画图画板
- 什么是CVR,CTR,CPC,CPA,ROI?
- Android音乐播放器(高分课设)
- [转]Mac 科研常用软件
热门文章
- linux系统苹果刷机,iPhone上安装Android系统详细步骤
- 《HybridSN: Exploring 3-D–2-DCNN Feature Hierarchy for Hyperspectral Image Classification》论文学习笔记
- 深度探索C++对象模型-Data语义学
- 有意思的atoll函数
- PLUPLOAD插件 ━━ 上传总结(分片上传,php后端处理)
- 口腔管理软件DSD微笑设计与正畸头影测量工具组合包简介
- linux 远程安装teamviewer,如何在CentOS 7上安装TeamViewer
- 四川省中小学计算机台球标准,《四川省中小学教育技术装备标准》.xls
- 电气、电子电路符号与表示方法
- 【内网渗透】搭建隧道