动静态库--Linux

本文详细介绍了动态链接与静态链接的区别,包括它们的工作原理和优缺点。动态链接生成的可执行文件体积小,依赖运行时加载的库,而静态链接则将库代码直接包含在程序中,不依赖外部库。静态库(.a)在编译时链接,程序运行不再需要,而动态库(.so)在运行时链接,多个程序可以共享。通过实例展示了如何生成和使用静态库及动态库,以及在Makefile中的应用。动态库利用了内存共享,节省了磁盘和内存资源。
摘要由CSDN通过智能技术生成

动态链接与静态链接的解释

通过命令ldd+可执行文件名,可以查看可执行文件中调用的库

 

库文件名和引入库的名称

如:libc.so-> c库,去掉前缀lib,去掉后缀.so或.a。

使用动态链接生成的可执行程序体积小,依赖库,在程序运行时加载库函数,可以只有一份。

使用静态链接生成的可执行程序体积较大,它是将对应的代码拷贝到可执行程序中,不依赖与库,可移植性强。

动态链接与静态链接的工作原理

动态链接

 

静态链接

 

静态库与动态库

  • 静态库(.a):程序在编译链接的时候把库里的代码链接到可执行文件中。程序运行的时候将不再需要静态库。

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

  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接。

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

实例:

//myadd.h
#ifndef __MYADD_H__
#define __MYADD_H__
int add(int a,int b);
#endif
​
//myadd.c
#include"myadd.h"
int add(int a,int b)
{
    return a+b;
}
​
//mysub.h
#ifndef __MYSUB_H__
#define __MYSUB_H__
int sub(int a, int b);
#endif
​
//mysub.c
#include"mysub.h"
int sub(int a,int b)
{
    return a-b;
}
​
//main.c
#include<stdio.h>
#include"myadd.h"
#include"mysub.h"
int main()
{
    int a=10;
    int b=20;
    printf("add(a,b)=%d\n",add(a,b));
    
    printf("sub(a,b)=%d\n",sub(a,b));
}

生成静态库

将add.c、sub.c生成add.o和sub.o,然后进行打包生成静态库

将头文件和生成的静态库分别放在mylib目录下的include目录和lib目录下

生成静态库的语法格式

ar -rc 生成的静态库名称,想要打包的.o文件

[ztl@VM-4-11-centos study_10-5]$ gcc -c mysub.c -o mysub.o
[ztl@VM-4-11-centos study_10-5]$ gcc -c myadd.c -o myadd.o
[ztl@VM-4-11-centos study_10-5]$ ls
makefile  myadd.c  myadd.h  myadd.o  mysub.c  mysub.h  mysub.o  test.c
//生成静态库
[ztl@VM-4-11-centos study_10-5]$ ar -rc libmymath.a *.o
[ztl@VM-4-11-centos study_10-5]$ ls
makefile  myadd.c  myadd.h  myadd.o  libmymath.a  mysub.c  mysub.h  mysub.o  test.c
ar是gnu归档工具,rc表示(replace and create)

libmymath.a就是打包好的静态库

使用Makefile打包静态库

libmymath.a:myadd.o mysub.o
    ar -rc $@ $^
myadd.o:myadd.c
    gcc -c $<
mysub.o:mysub.c
    gcc -c $<
​
.PHONY:clean
clean:
    rm -rf *.o output libmymath.a
​
.PHONY:output
output:
    mkdir -p mylib/include
    mkdir -p mylib/lib
    cp *.h ./mylib/include
    cp *.a ./mylib/lib
​
#make output:发布,生成对应目录,并将头文件和库拷贝至指定目录
查看静态库中的目录列表
[ztl@VM-4-11-centos study_10-5]$ ar -tv mylibmath.a
rw-rw-r-- 1001/1001   1240 Oct  5 14:01 2021 myadd.o
rw-rw-r-- 1001/1001   1240 Oct  5 14:01 2021 mysub.o
​
t:列出静态库中的文件
v:verbose 详细信息

使用静态库

Makefile中使用

test:test.c
    gcc test.c -o test -I./mylib/include -L./mylib/lib -lmymath -static
​
.PHONY:clean
clean:
    rm -f test
    
# -I,因为我们的头文件不在系统的默认目录或路径下,所以需要向编译器说明我们的头文件在哪。-I选项 + 头文件路径就表示告知编译器我们的头文件的路径
    
# -L,同样我们的库也不在默认目录与路径下,也需要向编译器说明我们生成的静态库在哪。-L选项 + 库的位置
     
# -l,虽然告诉了编译器头文件和目录的位置,但实际上,编译器不知道我们要用哪个库啊,一个lib目录下可能有多个库,所以要说明使用的库的名字(去掉后缀和前缀)
    
# -static 表示采用静态链接的方式编译,使用前需下载相关文件。使用命令:sudo yum install glibc-static

生成动态库

libmymath.so:myadd.o mysub.o
    gcc $^ -shared -o $@
myadd.o:myadd.c
    gcc -fPIC -c $<
mysub.o:mysub.c
    gcc -fPIC -c $<
    
.PHONY:clean
clean:
    rm -rf *.o output libmymath.so
    
.PHONY:output
output:
    mkdir -p mylib/include
    mkdir -p mylib/lib
    cp *.h ./mylib/include 
    cp *.so ./mylib/lib 
    
#shared: 表示生成共享库格式
#fPIC:产生位置无关码(position independent code)
#库名规则:libxxx.so

使用动态库

编译选项

与静态库相同,只是少了-static选项

gcc test.c -o test -L./mylib/lib -I./mylib/include -lmymath

执行:执行报错

执行ldd命令查看可执行文件所需要的库,可以发现我们自己打包的动态库并没有被找到,因为我们是按动态链接来编译的,编译器知道我们的库在哪,但是操作系统不知道。

所以我们要引入一个人环境变量LD_LIBRARY_PATH,里面放着动态库的路径,我们要把自己的库的路径放进去。

于是,要执行命令 export LD_LIBRARY_PATH=./mylib/lib/

这时就可以正常执行了

Makefile使用动态库

test:test.c
    gcc $^ -o $@ -I./mylib/include -L./mylib/lib -lmymath
.PHONY:clean
clean:
    rm -f test

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值