静态库与动态库

一. 静态库与动态库

1. 静态库:程序在编译链接的时候把库的代码链接到可执行文件中,程序运行的时候将不再需要静态库。
静态库命名格式是libxxx.a

2. 动态库:程序在运行的时候才去链接动态库的代码多个程序共享使用库的代码。一个与动态链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。
动态库命名格式是libxxx.so

动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

二. 那么我们该怎么生成静态库、动态库呢?又该怎么使用它们呢?

我们先写一段代码,做测试用

//add.h
#ifndef _ADD_H_
#define _ADD_H_
int add(int a, int b);
#endif
//sub.h
#ifndef _SUB_H_
#define _SUB_H_
int sub(int a, int b);
#endif
//add.c
#include "add.h"
int add(int a, int b)
{
    return a+b;
}
//sub.c
#include "add.h"
int sub(int a, int b)
{
    return a-b;
}
//main.c
#include <stdio.h>
#include "add.h"
#include "sub.h"
int main()
{
    int a=0;
    int b=0;
    scanf("%d %d", &a, &b);
    printf("%d + %d = %d\n", a, b, add(a, b));
    return 0;
}
1. 静态库

这里写图片描述
其中:
1. ar是gnu归档工具,rc表示replace and create
2. 可以使用ar -tv libsem.a来查看静态库中的目录列表,其中t:列出静态库中的文件,v:verbose详细信息
3. 生成静态库,接下来是生成我们的主程序了-L 指定库路径, -l指定库名
这里写图片描述
4. 可以发现,我们把静态库删除了,程序仍然是可以运行的,这正说明了程序把库的代码链接到了可执行文件中。

2. 动态库

这里写图片描述
其中:
1. shared:表示生成共享库格式; fPIC:产生位置无关码
什么是与位置无关?
我们知道,每一个进程都有自己独立的地址空间。在动态库链接的时候,可执行文件调用动态库的符号实际上是就是需要引用其他运行模块的符号了。对于可执行文件而言,将其加载到哪个地址并不关键,反正每个进程都有自己独一无二的地址空间,但是如果我们不将动态库编译成与位置无关的代码,那么在编译的时候,一定会把动态库加载到某个特定的地址上,如果动态库很多的话,就很有可能出现地址冲突。因此,建议大家还是加上-fPIC生成与位置无关的代码。
2. -l 链接动态库; L 链接库所在的路径
但是我们发现程序并没有运行成功。这是因为程序按照默认共享库路径找不到共享库文件。

三种方式可以解决这一问题:

  1. 将.so文件拷贝到系统共享库路径下,一般是指/usr/lib
    这里写图片描述
  2. 通过更改环境变量LD_LIBRARY_PATH
    这里写图片描述
    将动态库所在的路径设置为环境变量。
  3. 通过ldcinfig配置/etc/ld.so.conf.d/,ldconfig更新
    这里写图片描述
    将动态库所在的位置放到/etc/ld.so.conf.d/下的文件中,通过ldconfig更新,就可以运行成功了。

3.如果我们将动态库删了,那么代码也将不能运行了
这里写图片描述
4.动态库也是可执行程序的一种。
这里写图片描述
5.我们可以对比发现,用静态库生成的可执行文件的大小要比使用动态库生成的文件大。

6.共享库的调用方式有两种:显示调用和隐式调用。隐式调用是指在我们的程序代码中没有明确指定调用了哪些共享库,只是包含了对应的头文件,在编译的时候需要具体指明调用了哪个库。至于显示调用,我还没有了解到,有兴趣的可以参考这篇博客
通常,我们编写的程序默认使用的都是动态库,之前在写线程的相关程序时,就用到了线程库这一动态库

最后,再介绍一个Linux中的命令strip塑身,一般用于对静态库或动态库使用,删掉一些不必要的东西,使其变小。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值