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

news2025/4/3 3:18:50

一.对软硬链接的补充

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操作系统中,默认情况下安装的大部分库,都是动态库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2326228.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ubuntu22.04 如何安装 ch341 驱动

前言 本篇是介绍ubuntu22.04如何安装 ch341 驱动&#xff0c;并对其中遇到的问题进行整理。 一、流程 1.1 查看CH340驱动 首先是查看ubuntu22.04系统自带的驱动&#xff0c;用以下命令即可 ls /lib/modules/$(uname -r)/kernel/drivers/usb/serial 然后会跳出以下界面&…

个人博客网站从搭建到上线教程

步骤1:设计个人网站 设计个人博客网站的风格样式,可以在各个模板网站上多浏览浏览,以便有更多设计网站风格样式的经验。 设计个人博客网站的内容,你希望你的网站包含哪些内容如你的个人基本信息介绍、你想分享的项目、你想分享的技术文档等等。 步骤2:选择开发技术栈 因…

mac m4 Homebrew安装MySQL 8.0

1.使用Homebrew安装MySQL8 在终端中输入以下命令来安装MySQL8&#xff1a; brew install mysql8.0 安装完成后&#xff0c;您可以通过以下命令来验证MySQL是否已成功安装&#xff1a; 2.配置mysql环境变量 find / -name mysql 2>/dev/null #找到mysql的安装位置 cd /op…

UE5学习笔记 FPS游戏制作26 UE中的UI

文章目录 几个概念创建一个UI蓝图添加UI获取UI的引用 切换设计器和UI蓝图将UI添加到游戏场景锚点轴点slotSizeToContent三种UI数据更新方式(Text、Image)函数绑定属性绑定事件绑定 九宫格分割图片按钮设置图片绑定按下事件 下拉框创建添加数据修改样式常用函数 滚动框创建添加数…

Navicat导出mysql数据库表结构说明到excel、word,单表导出方式记录

目前只找到一张一张表导出的方式 使用information_schema传入表名查询 字段名根据需要自行删减&#xff0c;一般保留序号、字段名、类型、说明就行 SELECT COLUMNS.ORDINAL_POSITION AS 序号, COLUMNS.COLUMN_NAME AS 字段名, COLUMNS.COLUMN_TYPE AS 类型(长度), COLUMNS.N…

Linux驱动开发 中断处理

目录 序言 1.中断的概念 2.如何使用中断 中断处理流程 中断上下文限制 屏蔽中断/使能 关键区别与选择 上半部中断 下半部中断 软中断&#xff08;SoftIRQ&#xff09; 小任务(Tasklet) 工作队列&#xff08;Workqueue&#xff09; 线程 IRQ&#xff08;Threaded IRQ…

Centos主机检查脚本

使用方法&#xff1a; 将脚本保存为 CentOS_syscheck.sh 添加执行权限&#xff1a; chmod x CentOS_syscheck.sh 执行脚本&#xff1a; ./CentOS_syscheck.sh #!/bin/bash# 设置颜色变量 RED\033[0;31m GREEN\033[0;32m YELLOW\033[0;33m BLUE\033[0;34m NC\033[0m # 重置…

python系统之综合案例:用python打造智能诗词生成助手

不为失败找理由&#xff0c;只为成功找方法。所有的不甘&#xff0c;因为还心存梦想&#xff0c;所以在你放弃之前&#xff0c;好好拼一把&#xff0c;只怕心老&#xff0c;不怕路长。 python系列之综合案例 前言一、项目描述二、项目需求三、 项目实现1、开发准备2、代码实现 …

23种设计模式-结构型模式-桥接器

文章目录 简介问题解决方案示例总结 简介 桥接器是一种结构型设计模式&#xff0c;可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构&#xff0c;从而能在开发时分别使用。 问题 假如你有一个几何形状Shape类&#xff0c;它有两个子类&#xff1a;圆形C…

K8S学习之基础五十八:部署nexus服务

部署nexus服务 Nexus服务器是一个代码包管理的服务器&#xff0c;可以理解 Nexus 服务器是一个巨大的 Library 仓库。Nexus 可以支持管理的工具包括 Maven &#xff0c; npm 等&#xff0c;对于 JAVA 开发来说&#xff0c;只要用到 Maven 管理就可以了。Nexus服务器作用&#x…

Docker Desktop 界面功能介绍

Docker Desktop 界面功能介绍 左侧导航栏 Containers(容器): 用于管理容器,包括查看运行中或已停止的容器,检查容器状态、日志,执行容器内命令,启动、停止、删除容器等操作。Images(镜像): 管理本地 Docker 镜像,可查看镜像列表、从 Docker Hub 拉取新镜像、删除镜…

C++ set map

1.set和map是什么 set和map是 C STL 提供的容器&#xff0c;用于高效的查找数据&#xff0c;底层采用红黑树实现&#xff0c;其中set是Key模型&#xff0c;map是Key-Value模型 set和map的基本使用较为简单&#xff0c;这里不再叙述&#xff0c;直接进入实现环节 2.set和map的…

Spring AI Alibaba 对话记忆使用

一、对话记忆 (ChatMemory)简介 1、对话记忆介绍 ”大模型的对话记忆”这一概念&#xff0c;根植于人工智能与自然语言处理领域&#xff0c;特别是针对具有深度学习能力的大型语言模型而言&#xff0c;它指的是模型在与用户进行交互式对话过程中&#xff0c;能够追踪、理解并利…

Ubuntu24.04 离线安装 MySQL8.0.41

一、环境准备 1.1 官方下载MySQL8.0.41 完整包 1.2 上传包 & 解压 上传包名称是&#xff1a;mysql-server_8.0.41-1ubuntu24.04_amd64.deb-bundle.tar # 切换到上传目录 cd /home/MySQL8 # 解压&#xff1a; tar -xvf mysql-server_8.0.41-1ubuntu24.04_amd64.deb-bundl…

SOME/IP-SD -- 协议英文原文讲解10

前言 SOME/IP协议越来越多的用于汽车电子行业中&#xff0c;关于协议详细完全的中文资料却没有&#xff0c;所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块&#xff1a; 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 5.1.5 Non…

Ubuntu上给AndroidStudio创建桌面图标

最近使用了Ubuntu开发了&#xff0c;默认的android studio没有桌面图标&#xff0c;还是很不方便&#xff0c;每次都要cd到bin目录启动studio.sh。 步骤1&#xff1a;cd /usr/share/applications linux系统里面&#xff0c;所有的应用启动入口都在 /usr/share/applications …

简单视图函数

视图函数 文章目录 视图函数[toc]一、什么是视图函数二、简单视图函数三、返回错误视图 一、什么是视图函数 所谓视图函数&#xff08;简称视图&#xff09;&#xff0c;本质上就是一个Python函数&#xff0c;用于接收Web请求并且返回Web响应。Web响应可以包含很多类型&#x…

蓝桥杯备考----》完全背包模板

其实这个完全背包的步骤和01背包也是差不多滴&#xff0c;不过他有一些优化是我们必须要说一说的 老样子&#xff0c;我们先定义一下状态表示 step1: f[i][j]表示从1到i个物品里选出体积不超过j的最大价值 step2:状态转移方程 写成一行就是 我们再写一下f[i][j-v[i]]的表达…

小白入门机器学习概述

文章目录 一、引言二、机器学习的基础概念1. 机器学习的定义2. 机器学习的类型&#xff08;1&#xff09;监督学习&#xff08;Supervised Learning&#xff09;&#xff08;2&#xff09;无监督学习&#xff08;Unsupervised Learning&#xff09;&#xff08;3&#xff09;半…

微软 GraphRAG 项目学习总结

微软2024年4月份发布了一篇《From Local to Global: A GraphRAG Approach to Query-Focused Summarization》&#xff08;GraphRAG&#xff1a;从局部到全局的查询式摘要方法&#xff09;论文&#xff0c;提出了一种名为GraphRAG的检索增强生成&#xff08;RAG&#xff09;方法…