Linux中动静态库的生成与使用

0 定义

库可以看作是代码仓库,库里面封装了很多方法,当客户(也可以指程序员)需要使用时,可以直接导入库,然后调用库中的方法,可以很好的提高编程效率


 1 动静态库的区别?

        动静态库最大的区别除了体现在名字上(?)主要体现是在它们生成程序的链接阶段的时候。在链接阶段时,静态库会将自己的代码全部复制进程序中;而动态库则会进行分批加载

ps.linux中静态库的后缀名是.a  动态库的后缀名是.so

        分批加载

                在链接前,磁盘、地址空间、内存关系如下图所示:

                ​​​​​​此时,a.out被加载到内存上

                1.链接时,也就是需要调用动态库时,动态库会先加载到内存上

                2.如果程序碰到了需要使用的库中的方法,内存中的那个方法就会建立与页表间的链接

                3.此时代码会被加载到地址空间的共享区(栈与堆之间)里面

                4.当代码区里面的代码需要调用方法时,就会到共享区中调用

 ps.正是因为动态库中的文件是分批加载到共享区中的,所以如果多个程序使用这个库,那么他们可以共享库中的方法(都到一个地方去找),就不像静态库傻乎乎的全部复制到每一个程序代码中,更加节省空间。不过调用也会比静态库更,因为内存和地址空间之间需要建立映射关系,所以加载动态库的程序运行速度相对较慢。


结束了理论时间就来看看代码!

2 动静态库的链接(代码实操)

前期准备

首先我们先写个hello.c、math.c文件,准备把它编辑成库,代码如下:

 并在它们的头文件中声明这两个函数(这边省略),我们在写一个含有main函数的main.c来调用它们:

#include "mymath.h"
#include "hello.h"

int main()
{
    int x = 1;
    int y = 2;
    printf("x+y = %d\n",mymath(x,y));
    hello();
    return 0;
}

并把hello.c和mymath.c生成为后缀为.o的目标文件

gcc -c hello.c  -o hello.o 
gcc -c mymath.c -o mymath.o

静态库的生成与使用

我们用ar(归档)来生成静态库:

     //lib+文件名.a  后面跟.o文件
ar -rc libmylib.a hello.o mymath.o

此时文件中就生成了一个.a的静态库文件

        

我们把头文件和库放进另一个文件夹中,并把打包前的原.c和.o文件放到别的地方去(虽然打完包后不需要,但是后面编译动态库还需要),我们来模拟一下使用库的情况:

那么我们该怎么使用静态库呢?

  • 1.直接使用这个库
//-I 后面跟着头文件的路径
//-L 后面跟库的路径
//-l(小L)后面跟要使用的库名(不用加后缀也不用加前面的lib)
gcc main.c -o main -I ./a/include -L ./a/lib -lmylib

 编译成功后是可以运行的:

  •  2.把头文件和库文件直接拷贝到系统路径下

        系统路径下的头文件存放在:/usr/include

        系统路径下的库文件存放在:/usr/lib64

//到刚刚的include目录中,把.h文件复制进系统路径中
sudo cp *.h /usr/include

//复制库到系统路径中
sudo cp *.a /usr/lib64

复制后,就可以直接编译main.c文件并执行(记得也要指定库名!)


动态库的生成与使用

动态库的生成采用以下代码:

//fPIC 是告诉编译器要生成位置无关的代码 这是动态库的一个条件之一
//shared 告诉编译器生成的是.so动态库文件,而不是一个可执行文件的别名
gcc -fPIC -shared -o libmylib.so hello.c mymath.c

生成后,我们把动态库的库文件和头文件同样的放入其他的文件夹边:

 如何使用动态库?

  • 1.将库的地址存入环境变量LD_LIBRARY_PATH
                                       //你自己存放库的地址
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/zsy/class/io/ku/so/lib

 然后我们就可以直接编译生成可执行程序了,不过还是要指定库名。生成后我们再使用ldd(列出动态依赖关系)命令查看该可执行程序的动态依赖关系,可以看出连接的是动态库

 

 这个方法有不好的一点就是再次启动终端时就无法编译了,LD_LIBRARY_PATH命令会重置,所以我们可以看看另一种方法

  • 2.配置conf文件

        我们可以在路径/etc/ld.so.conf.d/里面创建自己的conf文件,并将库路径复制到里面,然后我们就可以永久使用了 

//创建mylib.conf文件到/etc/ld.so.conf.d/中
sudo touch /etc/ld.so.conf.d/ mylib.conf

/ect/ld.so.conf.d中的文件:

 然后我们 vim mylib.conf 把库所在路径复制进去(记得sudo!!)

 

 然后我们就可以直接编译咯(当然还是要指定库名)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值