linux下的静态库与动态库详解
静态库
先说说我们为什么需要库?
当有些代码我们大量会在程序中使用比如(scanf,printf等)这些函数我们需要在程序中频繁使用,于是我们就把这些代码编译为库文件,在需要使用时我们直接链接即可。
定义:
程序在编译时把静态库的代码链接到可执行程序中,在代码运行时不再需要静态库。(简单理解就是把一堆 .o 文件打包到一起,当需要用到就让我们的程序链接进来)
生成及使用方法:
这里用加减乘除来举例示意:
//创建所需文件
[root@localhost ku]# touch add.c add.h sub.c sub.h mul.c mul.h dev.c dev.h main.c
[root@localhost ku]# ls
add.c add.h dev.c dev.h main.c mul.c mul.h sub.c sub.h
[root@localhost ku]#
//编写所有文件代码
//add.c
#include"add.h"
int add(int x,int y)
{
return x+y;
}
//add.h
#ifndef __ADD_H__
#define __ADD_H__
int add(int x,int y);
#endif // __ADD_H__
//sub.c
#include"sub.h"
int sub(int x,int y)
{
return x-y;
}
//sub.h
#ifndef __SUB_H__
#define __SUB_H__
int sub(int x,int y);
#endif // __SUB_H__
//mul.c
#include"mul.h"
int mul(int x,int y)
{
return x*y;
}
//mul.h
#ifndef __MUL_H__
#define __MUL_H__
int mul(int x,int y);
#endif //__MUL_H__
//dev.c
#include"dev.h"
int dev(int x,int y)
{
return x/y;
}
//dev.h
#ifndef __DEV_H__
#define __DEV_H__
int dev(int x,int y);
#endif // __DEV_H__
//main.c
#include<stdio.h>
#include"add.h"
#include"sub.h"
#include"mul.h"
#include"dev.h"
int main()
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d + %d = %d\n",a,b,add(a,b));
printf("%d - %d = %d\n",a,b,sub(a,b));
printf("%d * %d = %d\n",a,b,mul(a,b));
printf("%d / %d = %d\n",a,b,dev(a,b));
return 0;
}
//编译源文件
[root@localhost ku]# ls
add.c add.h dev.c dev.h main.c mul.c mul.h sub.c sub.h
[root@localhost ku]# gcc -c *.c //把所有.c文件生成.o文件
[root@localhost ku]# ls
add.c add.h add.o dev.c dev.h dev.o main.c main.o mul.c mul.h mul.o sub.c sub.h sub.o
[root@localhost ku]# rm main.o -rf //删除多余的.o文件
[root@localhost ku]# ls
add.c add.h add.o dev.c dev.h dev.o main.c mul.c mul.h mul.o sub.c sub.h sub.o
[root@localhost ku]#
//生成静态库
[root@localhost ku]# ar -rc libmycal.a *.o
[root@localhost ku]# ls
add.c add.h add.o dev.c dev.h dev.o libmycal.a main.c mul.c mul.h mul.o sub.c sub.h sub.o
[root@localhost ku]#
//查看静态库
[root@localhost ku]# ls
add.c add.h add.o dev.c dev.h dev.o libmycal.a main.c mul.c mul.h mul.o sub.c sub.h sub.o
[root@localhost ku]# ar -tv libmycal.a
rw-r--r-- 0/0 683 Apr 26 20:46 2018 add.o
rw-r--r-- 0/0 683 Apr 26 20:46 2018 dev.o
rw-r--r-- 0/0 679 Apr 26 20:46 2018 mul.o
rw-r--r-- 0/0 687 Apr 26 20:46 2018 sub.o
[root@localhost ku]#
//链接静态库生成可执行文件
[root@localhost ku]# ls
add.c add.h add.o dev.c dev.h dev.o libmycal.a main.c mul.c mul.h mul.o sub.c sub.h sub.o
[root@localhost ku]# gcc main.c -L. -lmycal
[root@localhost ku]# ls
add.c add.h add.o a.out dev.c dev.h dev.o libmycal.a main.c mul.c mul.h mul.o sub.c sub.h sub.o
[root@localhost ku]#
//运行结果
[root@localhost ku]# ls
add.c add.h add.o a.out dev.c dev.h dev.o libmycal.a main.c mul.c mul.h mul.o sub.c sub.h sub.o
[root@localhost ku]# ./a.out
8 3
8 + 3 = 11
8 - 3 = 5
8 * 3 = 24
8 / 3 = 2
[root@localhost ku]#
以上是整个静态库的生成及运用过程
总结起来就3步骤:
首先将源文件编译成目标文件:gcc –c 源文件
生成静态库:ar –rc lib(库名).a 目标文件
使用静态库:gcc main.c -L(库的路径) -l(库名)
静态库的优缺点
优点:
1. 省空间:linker只会复制你用到的objects。
2. 打包简单。
缺点:
1、如果静态库中有全局变量,那么在几个模块中使用,将会导致全局变量有不同的值,这是非常严重的问题。
2、静态库编译时,不会进行链接检查,所以这么多静态库的问题,在生成静态库阶段检查不出来。
3、几个模块,引用同一静态库,如果有一模块没有编译到,会引起巨大的差异导致问题。
4.产生大量的库文件文件会占空间
动态库
定义:
程序在运行时才去链接动态库的代码,多个程序共享使用库的代码。
一个与动态库链接的可执行文件仅包含他用到的函数入口地址的一个表,而不是外部函数所在目标文件的机器码。
生成及使用方法:
事例程序和上面一样,这里只写出操作步骤
[root@localhost ku]# ls
add.c add.h dev.c dev.h main.c mul.c mul.h sub.c sub.h
[root@localhost ku]# gcc -c -fpic *.c
// -fpic 表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
[root@localhost ku]# ls
add.c add.h add.o dev.c dev.h dev.o main.c main.o mul.c mul.h mul.o sub.c sub.h sub.o
[root@localhost ku]# rm main.o -rf
[root@localhost ku]# ls
add.c add.h add.o dev.c dev.h dev.o main.c mul.c mul.h mul.o sub.c sub.h sub.o
[root@localhost ku]# gcc -shared -o libmycal.so *.o
[root@localhost ku]# ls
add.c add.h add.o dev.c dev.h dev.o libmycal.so main.c mul.c mul.h mul.o sub.c sub.h sub.o
[root@localhost ku]# gcc main.c -L. -lmycal
//-L. 表示要连接的库在当前目录中
[root@localhost ku]# ls
add.c add.h add.o a.out dev.c dev.h dev.o libmycal.so main.c mul.c mul.h mul.o sub.c sub.h sub.o
[root@localhost ku]# ./a.out
./a.out: error while loading shared libraries: libmycal.so: cannot open shared object file: No such file or directory
[root@localhost ku]# cp libmycal.so /lib/
//把动态库移动到系统库文件下
[root@localhost ku]# ls
add.c add.h add.o a.out dev.c dev.h dev.o libmycal.so main.c mul.c mul.h mul.o sub.c sub.h sub.o
//运行结果
[root@localhost ku]# ./a.out
8 6
8 + 6 = 14
8 - 6 = 2
8 * 6 = 48
8 / 6 = 1
//第二种方法,更改库路径
[root@localhost ku]# ./main
./main: error while loading shared libraries: libmycal.so: cannot open shared object file: No such file or directory
[root@localhost ku]# vim /etc/ld.so.conf.d/mycal.conf //在创建的文件里写上库的路径
//写好路径之后刷新缓冲区
[root@localhost ku]# ldconfig
//运行结果
[root@localhost ku]# ./main
8 6
8 + 6 = 14
8 - 6 = 2
8 * 6 = 48
8 / 6 = 1
动态库优缺点:
优点:
1 .共享内存
2 .独立升级组件(插件安装,软件更新)
3.可以显示动态加载
缺点:
1.当系统中多个应用程序都用了一个动态链接库,但是要求的版本不同,这时动态链接库之间就会相互干扰。
2.性能开销。动态链接库为了做到“共享代码,但是不共享数据”,引入了不小的开销,调用动态链接库中的函数,需要好几次间接内存访问才能走到函数入口,全局数据也是。
linux下的静态库与动态库详解的更多相关文章
- Linux下nginx编译安装教程和编译参数详解
这篇文章主要介绍了Linux下nginx编译安装教程和编译参数详解,需要的朋友可以参考下 一.必要软件准备1.安装pcre 为了支持rewrite功能,我们需要安装pcre 复制代码代码如下: # y ...
- Linux下的I/O复用与epoll详解(转载)
Linux下的I/O复用与epoll详解 转载自:https://www.cnblogs.com/lojunren/p/3856290.html 前言 I/O多路复用有很多种实现.在linux上,2 ...
- Linux 下的静态(函数)库、动态(函数)库
0. 基本 在命名上,静态库的名字一般是 libxxx.a,动态库的名字一般是 libxxx.so,有时 libxxx.so.major.minor,xxx 是该 lib 的名字,major 是主版本 ...
- linux下添加动态链接库路径、动态库加载等方法
linux下添加动态链接库路径的方法 2017年01月20日 10:08:17 阅读数:5596 Linux共享库路径配置 Linux下找不到共享库文件的典型现象为明明已经安装某个软包(如libn ...
- JNI静态注册与动态注册详解
JNI注册,是指将java层方法(native关键字修饰的)和C层方法对应起来,以实现java层代码调用c层代码的目的.JNI注册分为静态注册和动态注册两种,静态注册是通过固定格式方法名进行关联,动态 ...
- linux下项目开发加载动态库:ldconfig与 /etc/ld.so.conf
场景:自己开发一个项目,程序里包含一些自定义动态库.运行,需要加载这些动态库. 假如这些库在/pro/output/lib/下面,可执行程序在/pro/output/bin/下面. 那么,我们需要: ...
- Apache静态编译与动态编译详解
Apache拥有4层结构,从核心到外层的module.而外层的module可以用通过静态和动态两种方式与Apache共同工作.这也就引入下文的“动态”和“静态”两种编译安装方式: 静态编译: 编译的时 ...
- Linux 下 svn 场景实例及常用命令详解
一.SVN使用场景实例 问题: 在使用svn做为版本控制系统的软件开发中,经常会有这样的需求:在工作复本目录树的不同目录中增加了很多文件,但未纳入版本控制系统,这时如果使用svn add命令一个一个的 ...
- Linux下的压缩zip,解压缩unzip命令详解及实例
实例:压缩服务器上当前目录的内容为xxx.zip文件 zip -r xxx.zip ./* 解压zip文件到当前目录 unzip filename.zip ====================== ...
- Linux下添加硬盘,分区,格式化详解
2005-10-17 在我们添加硬盘前,首先要了解linux系统下对硬盘和分区的命名方法. 在Linux下对IDE的设备是以hd命名的,第一个ide设备是hda,第二个是hdb.依此类推 我们一般主板 ...
随机推荐
- 使用TortoiseSVN打Tag
参考了 https://blog.csdn.net/liuzx32/article/details/9123401. 值得注意的点是: 选择路径的时候,不要先点进去自己建好叶子节点路径再选择该路径,会 ...
- 27.C++- 智能指针
智能指针 在C++库中最重要的类模板之一 智能指针实际上是将指针封装在一个类里,通过对象来管理指针. STL中的智能指针auto_ptr 头文件: <memory> 生命周期结束时,自动摧 ...
- Hadoop API:遍历文件分区目录,并根据目录下的数据进行并行提交spark任务
hadoop api提供了一些遍历文件的api,通过该api可以实现遍历文件目录: import java.io.FileNotFoundException; import java.io.IOExc ...
- ArUco----一个微型现实增强库的介绍及视觉应用(一)
ArUco----一个微型现实增强库的介绍及视觉应用(一) 一.ArUco简介 ArUco是一个开源的微型的现实增强库,目前好像已经集成在OpenCV3.0以上的版本内了,它除了用于现实增强,还很用于 ...
- MySQL 如何使用 PV 和 PVC?- 每天5分钟玩转 Docker 容器技术(154)
本节演示如何为 MySQL 数据库提供持久化存储,步骤为: 创建 PV 和 PVC. 部署 MySQL. 向 MySQL 添加数据. 模拟节点宕机故障,Kubernetes 将 MySQL 自动迁移到 ...
- [转]map函数补充
map()函数 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 例如,对于li ...
- 重拾Python(3):Pandas之Series对象的使用
Pandas是Python下最强大的数据分析和探索库,是基于Numpy库构建的,支持类似SQL的结构化数据的增.删.查.改,具有丰富的数据处理函数.Pandas有两大数据结构:Series和DataF ...
- 深入理解Redux
前面的话 Redux是Flux思想的另一种实现方式.Flux是和React同时面世的.React用来替代jQuery,Flux用来替换Backbone.js等MVC框架.在MVC的世界里,React相 ...
- 【省带宽、压成本专题】从产品架构来看,PCDN如何节流50%
过去几年,我们一直在视频省流量方面潜心钻研,取得不俗的成果.本次"省带宽.压成本"系列一共会推出六篇文章,从技术迭代.硬件更新等角度出发,向大家介绍节省CDN流量,降低视频播放成本 ...
- WPF 自定义TabControl控件样式
一.前言 程序中经常会用到TabControl控件,默认的控件样式很普通.而且样式或功能不一定符合我们的要求.比如:我们需要TabControl的标题能够居中.或平均分布:或者我们希望TabContr ...