当前位置: 首页 > news >正文

【Linux】动静态库的制作与使用

一.对软硬链接的补充

1、无法对目录进行硬链接

 为什么呢?

首先,我们在访问文件时,每一个文件都会有自己的dentry结构,这些结构会在内存中维护一棵路径树,来快速进行路径查找。但是如果某个节点直接使用硬链接到了根节点/某个节点,此时就会在树中出现环路。这就会导致再路径树种查找路径出现死循环的情况。

所以再Linux操作系统中,不支持给目录创建硬链接,而只能给普通文件硬链接。

但其实我们每个目录底下的两个隐藏文件.和..其实也是硬链接,但它们属于系统开了绿灯,因为它们是特殊字符,所以在查找时可以特殊处理,不易导致路径环问题。

2、可以对目录进行软链接

首先,软链接出来的文件才是实际意义上的链接文件,因为它的开头是l

并且,软链接之后的文件有独立的inode,它的内容是目标路径字符串。所以它并不会直接的影响路径树的结构,它只是通过类似解引用的方式实现访问目标路径的目的。

3、要想删除一个软/硬链接,除了直接删除链接的文件,也可以使用unlink命令,取消链接属性

二.什么是库?

我们学习c/c++至今,每一次代码的编写都使用到了c/c++的标准库。库其实就是将一些常用的方法总结了起来,并进行实现,之后当我们再需要使用该方法时,就直接使用库中实现好的即可。

所以,库其实就是常用方法的二进制集合。

本质上,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库分为两种:

  • 静态库Linux(.a) windows(.lib)
  • 动态库Linux(.so) windows(.dll)

 三.静态库的制作与使用

现在,我们实现了加法方法和减法方法,将其制作成为库。

0x1.阶段1

在没有将其形成库之前,如果想要用户使用我们的方法,我们就得将我们实现的所有.h文件和.c文件直接给用户。但是,直接将.c给用户,这不就把我们实现的方法给暴露了么,我只给你用,但你不能看我具体的实现。

所以,我们就先将.c文件通过遍历但不链接形成同名的.o文件,然后将头文件和.o目标文件给用户使用即可。

 而在用户视角,我们拿到了.h和,.o文件,然后只需要编写自己的代码即可。最后将所有的.o文件链接起来即可。

 通过gcc命令对所有的.o目标文件进行链接,形成可执行程序。

 0x2.阶段2

虽然这样用户可以使用我们的方法,但是如果我们实现的方法有几百上千个头文件和源文件呢?我们需要将这么多个源文件都生成.o文件,再传给用户。虽然这样对我们没什么,但是对用户就有点麻烦了。

所以,我们可以先将所有的.o目标文件打包成为一个库,再将该库和头文件发给用户使用即可。这样用户就不必接收多个目标文件了。

ar -rc dst src

使用上述命令,将所有的.o文件进行归档,形成一个归档文件。另外,我们形成的静态库要以.a结尾(.a后面还可以跟其他后缀),以lib开头,并且我们静态库真正的名字是去掉前后lib和后缀.a之后剩余的部分。

 有了静态库,在用户方,就只需要拿到静态库和头文件即可。用户使用的时候,可以直接将该静态库与自己的.o目标文件进行链接。

.a文件本质上是一种归档文件,不需要使用者进行解包,而直接使用gcc/g++直接链接即可。

gcc -o code usercode.o -l mymethod

 我们使用-l选项,告诉编译器我要链接哪一个库。

但是直接这样,编译器是找不到库的,因为编译器默认只会在系统指定的目录下寻找动静态库。所有想要使用我们自己的库,还要使用-L选项,指定静态库的位置。 

gcc -o code usercode.o -L . -l mymethod

 0x3.阶段3

虽然形成静态库,避免了多个目标文件的问题,但是头文件依旧很多。所以一般的做法都是新建目录,在该目录下创建include和mylib子目录,分别将头文件和库放入这两个目录下,然后将这个目录的内容压缩发送给用户。

 然后用户就在使用gcc来进行链接操作,但是这次链接时,gcc命令还要多加一个选项 -I(大写i),用来指定寻找头文件的路径

gcc -o code usercode.o -I ./lib/include -L ./lib/mylib/ -l mymethod

-I选项就是告诉编译器,除了在系统指定的目录下搜索头文件,也要从我指定的目录下,搜索头文件。 

至此,静态库的制作和使用就结束了。

四.动态库的制作与使用

动态库的制作直接使用gcc遍历器来生成。我们写一个makefile来自动化构建我们的动态库以及头文件与动态库的打包。

libmymethod.so:add.o sub.o
	gcc -o $@ $^ -shared
%.o:%.c
	gcc -fPIC -c $<

.PHONY:output
output:
	mkdir -p dylib/include
	mkdir -p dylib/mylib
	cp -f *.h dylib/include
	cp -f *.so dylib/mylib
	tar czf dylib.tgz dylib

.PHONY:clean
clean:
	rm *.o *.so

生成动态库时用gcc命令时要加上-shared选项,表示生成共享库格式

另外,在生成目标文件时,也要加上选项 -fPIC:产生位置无关码

我们将生成好的压缩包传给用户,让用户使用动态库。生成动态库时要以lib开头,.so结尾,剩余部分才是真正的动态库名。

我们在链接动态库时并不会出现问题,可以生成对应的可执行程序,但是在执行的时候,就会报错,说找不到我们自己的动态库?

 我们可以使用ldd命令,查看可执行程序所使用的动态库!

我们看到,我们自己的动态库确实没有被找到,这是为什么呢?我们不是在编译的时候指定了在哪里找我们的动态库了么?

原因是:我们在链接的时候指定动态库的位置,只是让编译器找到了动态库,可是系统并不知道!!!操作系统并不等于编译器。而操作系统查找动态库只会在系统指定的目录下查找,所以找不到我们的动态库。

这与静态库不同,链接静态库实际上就是将静态库的内容拷贝到自己的代码中,所以在使用静态链接之后,静态库便没有用了。

而我们使用动态库,默认采取动态链接,动态链接后的可执行程序内部并没有库方法的实现,它类似于函数调用,指定到库方法时会跳转到对应的动态库中,执行完毕再返回。所以动态链接对动态库的依赖性很大。所以,使用动态库后,系统必须得找到对应的动态库。

那怎么解决呢?

法1:将我们的动态库拷贝到系统中

法2:建立同名软链接

法3:将动态库所在路径添加至环境变量LD_LIBRARY_PATH中

操作系统查找动态库,除了再指定的系统目录下查找,也会再环境变量LD_LIBRARY_PATH中查找。

但是,我们的环境变量是内存级的,当我们退出终端之后,环境变量就会被还原。我们可以修改配置文件来达到永久修改环境变量的目的。

法4:在/etc/ld.so.conf.d/下新建一个conf文件,并将动态库所在路径写入 

但是注意,我们写入之后依旧无法直接使用,我们得使用ldconfig命令重新加载库更新路径,之后便可以生效

五.总结 

1.动静态库中,其实根本不需要包含main函数,所有的库不论动静,本质上都是源文件对应的.o目标文件。

2.gcc/g++链接所有非c/c++标准库,都需要指明-L -l。

3.所有我们所说的将库安装到系统中,实际上就是将库拷贝到对应的系统目录下。

4.gcc/g++,在动态和静态库都存在的情况下,默认使用动态库

 如果非得静态链接,必须加-static选项

如果只存在静态库,那就只能使用静态链接 

5.在Linux操作系统中,默认情况下安装的大部分库,都是动态库

相关文章:

  • AI知识补全(十):AI伦理与安全是什么?
  • 召唤数学精灵
  • Jiangxi Province Baseball Softball Development Plan【江西棒垒球】
  • AI提示语:生成演示文稿 PPT
  • 将内网的IP地址映射到外网的几种方案
  • 堆叠虚拟化
  • Spring Boot分布式项目重试实战:九种失效场景与正确打开方式
  • JavaScript中 == 和 === 区别
  • 汇编语言学习前言
  • Java Spring Boot 与前端结合打造图书管理系统:技术剖析与实现
  • 12-SpringBoot3入门-项目打包和运行
  • 【力扣hot100题】(024)环形链表
  • kali配置固定IP
  • AI 数字人短视频数字人口播源码:短视频内容生产的新引擎​
  • axios介绍以及配置
  • 【LeetCode】二叉树的递归遍历
  • promise使用及其方法
  • CMake在Windows环境下Visual Studio Code的使用
  • 利用deepseek直接调用其他文生图网站生成图片
  • [VolgaCTF 2025] Baby-Welcome,BrokeBroke,Field Rules
  • 小额贷款网站怎么做/如何发布视频赚钱
  • 建设工程规划许可证公示网站/seo学院
  • 深圳网站建设的基/搜索引擎是网站吗
  • 建设电子商务网站的规划书/搜狗收录提交
  • 大连网站建设找简维科技/建材企业网站推广方案
  • 网站导航栏种类/公司怎么做网络营销