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

动静态库-Linux 学习

在软件开发中,程序库是一组预先编写好的程序代码,它们存储了常用的函数、变量和数据结构等。这些库可以帮助开发者节省大量的时间和精力,避免重复编写相同的代码。当我们在 Linux 系统中开发程序时,经常会用到两种类型的程序库:静态库和动态库。

  • 静态库 (.a):静态库是指在程序编译时,将库文件中的代码直接复制到可执行文件中。这意味着当程序运行时,库文件中的代码已经包含在可执行文件中,不需要在运行时进行加载。
  • 动态库 (.so):动态库是指在程序运行时才加载的库文件。程序本身不包含库文件的代码,而是通过链接到动态库来调用其中的函数和数据结构等。动态库通常以共享库的形式存在,多个程序可以共享一个动态库。

从库的制作者角度

静态库

我们可以自己尝试写一个简单的计算程序来实现简单的加减乘除功能。

我们可以先创建以下文件:

加法:Add.c , Add.h
减法:Sub.c , Sub.h
乘法:Mul.c , Mul.h
除法:Div.c , Divh

image.png

如果我们要上面的文件形成一个库,我们是不能在上面的这些文件中写main函数的,因为库中是没有main 函数的,我们也不能把main 函数打入库中。

// Add.h
#pragma once // 防止头文件被重复包含
#include <stdio.h>
int Add(int,int);
----------------------------
// Add.c
#include "Add.h"
int Add(int x, int y)
{return x + y;
}
// Sub.h
#pragma once
#include <stdio.h>
int Sub(int,int);
----------------------------
// Sub.c#include "Sub.h"
int Sub(int x, int y)
{return x - y;
}
//Mul.h
#pragma once
#include <stdio.h>
int Mul(int,int);
----------------------------
// Mul.c#include "Mul.h"
int Mul(int x, int y)
{return x * y;
}
//Div.h
#pragma once
#include <stdio.h>
int Div(int,int,int*);
------------------------------
// Div.c#include "Div.h"
int Div(int x, int y, int *code)
{*code = 0;if (y == 0){*code = -1;return -1;	}return x / y;
}

我们现在要将上面的一堆的头文件 和 源文件 形成静态库

为 我们的方法进行测试,我们可以建立一个叫TestMain.c 的文件。

// TestMain.c
#include "Add.h"
#include "Sub.h"
#include "Mul.h"
#include "Div.h"int x = 20;int y = 10;printf("%d + %d = %d\n",x, y, Add(x,y));printf("%d - %d = %d\n",x, y, Sub(x,y));printf("%d * %d = %d\n",x, y, Mul(x,y));

我们可以运行一下上面的测试程序TestMain.c,不过我们要先进行编译:

// Linux 系统 gcc -o test Add.c Sub.c Mul.c Div.c TestMain.c// 我们在编译的时候没有加上头文件,因为当前的头文件和源文件是在同一个路径下的,所以我们不用加上头文件。

上面我们是把所有的源文件都进行了编译的,其实如果我们要形成一个可执行程序,我们不太建议将所有的源文件都直接进行编译,因为我们一旦这样做,每一个源文件都要进行预处理,编译,汇编,链接。所以一般在面对这样的多文件项目时我们一般都建议把这样的源文件编译成.o 文件。编译成.o 文件之后,然后我们在把所有的.o 文件进行对应的链接 形成一个可执行。

.c–(预处理,编译,汇编)—> .o ----(链接)----> 可执行

// 介绍一下`-c` 的选项。
gcc -c test.c // 在 test.c形成可执行前(即:链接前) 终止,最终会生成一个`.o` 的文件,默认是同名的`test.o`

所以如果我们把上面文件中的TestMain.o 去掉,为什么要去掉呢?因为如果我们要做一个静态库,库中是不能有main 函数的,main 函数只能是用这个库的用户写的。这样一来就只剩下Add.0,Sub.o,Mul.o,Div.o 了,我们只需要对Add.0,Sub.o,Mul.o,Div.o 这些.o 文件进行打包,以后如果某个用户想要用到这些加减乘除的方法,只需要将自己写的main 函数编译成xxx.o 文件,然后再和打包好的文件中的.o 文件进行链接就好了。

生成静态库

那我们如何对我们的.o文件进行打包呢?

ar 命令
ar命令是一个把所有的.o 文件打包形成我们对应的库文件的过程。

 ar -rc libmymath.a add.o sub.o 

ar是gnu归档工具,选项:rc表示(replace and create),他的意思是:把所有的.o文件打包生成一个.a 文件,如果存在就替换(replace)如果不存在就创建(create)。

库的名字要以lib 开头,以.a 结尾,所以上面我们的库是mymath ,但是加上前缀和后缀之后就是:libmymath.a 了。

静态库的原理就是将库中的源代码直接翻译成.o 目标二进制文件,然后打包

动态库

一、什么是动态库?

动态库,也叫共享库(Shared Library),是一种在程序运行时才被加载到内存中的代码库。它的文件名通常以 libxxx.so 的形式命名(xxx 是库的名字,so 表示 shared object)。
与动态库相对的是静态库(Static Library),静态库在程序编译时会被直接嵌入到可执行文件中,文件名通常以 libxxx.a 的形式命名。

二、生成动态库

1. 编译选项

生成动态库需要使用 gcc 编译器,并指定以下选项:

  • -fPIC:生成位置无关代码(Position Independent Code, PIC)。这种代码可以在内存中的任何位置运行,是动态库的必要条件。
  • -shared:表示生成共享库格式。
2. 示例代码

假设我们有以下文件:

  • add.c:实现加法函数。
  • sub.c:实现减法函数。

文件内容如下:

// add.c
#include <stdio.h>int add(int a, int b) {return a + b;
}
// sub.c
#include <stdio.h>int sub(int a, int b) {return a - b;
}
3. 生成动态库的步骤
# 编译源文件为位置无关代码
gcc -fPIC -c add.c sub.c# 生成动态库
gcc -shared -o libmymath.so add.o sub.o

执行完上述命令后,会生成一个名为libmymath.so 的动态库文件。

从库的使用者角度

静态库的使用

上面我们自己写的库libmymath.a 是第三方库,gcc 默认不认识 。所以我们在使用gcc D的时候还要加上一个-l 选项来链接到我们的库,还记得上面我们所说的吗,我们的库是以lib为前缀的,以.a 为后缀的,但是在用-l 链接的时候,我们要去掉前缀和后缀,直接用mymath 像这样:-lmymath ,我们还要用-L 来制定库的路径,我们这样来表示-L. ,用. 来表示当前路径,如果你的静态库在当前路径下的话,所以连在一起就是:

[root@localhost linux]# gcc TestMain.c -L. -lmymath
  • TestMain.c 是用户写的程序。
  • -L 指定库路径
  • -l 指定库名
  • -I : 指定头文件的路径

如果我们要把自己写的库交给其他用户使用的话,那我们就要把.h.a 交给他,

gcc 默认是动态链接的,

动态库的使用

使用动态库

1. 编译选项

在使用动态库时,需要指定以下选项:

  • -L:指定动态库所在的路径(如果动态库不在系统默认路径中)。
  • -l:指定要链接的动态库的名字(去掉 lib 前缀和 .so 后缀)。
2. 示例代码

假设我们有一个主程序 main.c,它调用了动态库中的函数:

// main.c
#include <stdio.h>int add(int a, int b);
int sub(int a, int b);int main() 
{printf("add(10, 20) = %d\n", add(10, 20));printf("sub(100, 20) = %d\n", sub(100, 20));return 0;
}
3. 编译主程序
# 编译主程序
gcc main.c -o main -L. -lmymath
  • -L. 表示动态库在当前目录下。
  • -lmymath 表示链接 libmymath.so 动态库。

运行动态库

方法一:将 .so 文件拷贝到系统共享库路径

系统默认的动态库路径通常是 /usr/lib/usr/local/lib或是:/lib64 。可以将动态库文件拷贝到这些路径下:

# 拷贝动态库到 /usr/local/lib
cp libmymath.so /usr/local/lib/
方法二:通过使用软连接 查找动态库
ln -s /*动态库的路径*/ libmymath.so

/*动态库的路径*/ : 这里填动态库的路径

libmymath.so : 这个是软连接的名字。

这样,我们通过在当前目录下建立软连接的方式找到我们对应的库。
gcc 可以在当前目录下找到动态库。所以我们可以在当前目录下建立对应库的软连接,这样来让 gcc 找到,我们也可以在系统的指定目录下建立对应的软连接。

方法三:设置 LD_LIBRARY_PATH 环境变量(LD 的意思就是 load -加载,所以这句话就是 : 加载库路径环境变量)

如果不想将动态库文件拷贝到系统路径,可以通过设置 LD_LIBRARY_PATH 环境变量来指定动态库的路径:

# 设置 LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/*这里填你写的动态库的路径*/

但是这里导入的环境变量是内存级的,所以你重启电脑之后就没了。

方法四:直接更改系统配置文件:使用 ldconfig 配置动态库路径

如果动态库文件存放在非默认路径下,可以通过修改 /etc/ld.so.conf 文件或在 /etc/ld.so.conf.d/ 下添加配置文件来指定动态库路径。

例如:

# 创建配置文件
echo "/path/to/your/library" > /etc/ld.so.conf.d/mylib.conf# 更新动态库缓存
ldconfig

同一组库,提供动静两种库,gcc默认使用动态库。

五、使用外部库

Linux 系统中有很多外部库,例如:

  • ncurses:用于处理屏幕显示和用户输入的库。
  • glib:用于通用工具函数的库。
  • openssl:用于加密和安全通信的库。

使用外部库的步骤与使用自己编写的动态库类似,需要:

  1. 安装外部库(通常通过包管理工具,如 aptyum)。
    比如安装ncurses
    sudo yum install -y ncurses-devel
  2. 在编译时指定库的路径和名称。

例如,使用 ncurses 库:

# 编译
gcc main.c -o main -lncurses# 运行
./main

相关文章:

动静态库-Linux 学习

在软件开发中&#xff0c;程序库是一组预先编写好的程序代码&#xff0c;它们存储了常用的函数、变量和数据结构等。这些库可以帮助开发者节省大量的时间和精力&#xff0c;避免重复编写相同的代码。当我们在 Linux 系统中开发程序时&#xff0c;经常会用到两种类型的程序库&am…...

【Hudi-SQL DDL创建表语法】

CREATE TABLE 命令功能 CREATE TABLE命令通过指定带有表属性的字段列表来创建Hudi Table。 命令格式 CREATE TABLE [ IF NOT EXISTS] [database_name.]table_name[ (columnTypeList)]USING hudi[ COMMENT table_comment ][ LOCATION location_path ][ OPTIONS (options_lis…...

HTML label 标签使用

点击 <label> 标签通常会使与之关联的表单控件获得焦点或被激活。 通过正确使用 <label> 标签&#xff0c;可以使表单更加友好和易于使用&#xff0c;同时提高整体的可访问性。 基本用法 <label> 标签通过 for 属性与 id 为 username 的 <input> 元素…...

bge-large-zh-v1.5 与Pro/BAAI/bge-m3 区别

ge-large-zh-v1.5 和 Pro/BAAI/bge-m3 是两种不同的模型&#xff0c;主要区别在于架构、性能和应用场景。以下是它们的对比&#xff1a; 1. 模型架构 bge-large-zh-v1.5&#xff1a; 基于Transformer架构&#xff0c;专注于中文文本的嵌入表示。 参数量较大&#xff0c;适合处…...

JVM常用概念之对象初始化的成本

在JVM常用概念之新对象实例化博客中我讲到了对象的实例化&#xff0c;主要包含分配&#xff08;TLAB&#xff09;、系统初始化、用户初始化&#xff0c;而我在JVM常用概念之线程本地分配缓冲区&#xff08;ThreadLocal Allocation Buffer&#xff0c;TLAB&#xff09;博客中也讲…...

[AI机器人] Web-AI-Robot机器人前瞻版--比奇堡海之霸凯伦

文章目录 简述开源Web-AI-Robot 项目-比奇堡-海之霸-凯伦 技术架构效果预览 简述 本项目配合前端项目bikini_bottom_karen_ui运行&#xff0c;来源于柒杉工作室&#xff08;截止2025.2&#xff0c;目前我自己&#xff09;。 打造一个只需要在浏览器上运行的AI智能机器人&#…...

嵌入式学习-EXTI外部中断

STM32 是一种基于 ARM Cortex-M 内核的微控制器系列&#xff0c;广泛应用于嵌入式系统开发。中断&#xff08;Interrupt&#xff09;是 STM32 中一个非常重要的功能&#xff0c;它允许微控制器在执行主程序的同时&#xff0c;响应外部事件或内部事件的请求&#xff0c;从而实现…...

CSS—元素水平居中:2分钟掌握常用的水平居中

个人博客&#xff1a;haichenyi.com。感谢关注 1. 目录 1–目录2–行内元素水平居中3–块级元素水平居中 2. 行内元素水平居中 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" …...

PyTorch 中结合迁移学习和强化学习的完整实现方案

结合迁移学习&#xff08;Transfer Learning&#xff09;和强化学习&#xff08;Reinforcement Learning, RL&#xff09;是解决复杂任务的有效方法。迁移学习可以利用预训练模型的知识加速训练&#xff0c;而强化学习则通过与环境的交互优化策略。以下是如何在 PyTorch 中结合…...

大语言模型学习--本地部署DeepSeek

本地部署一个DeepSeek大语言模型 研究学习一下。 本地快速部署大模型的一个工具 先根据操作系统版本下载Ollama客户端 1.Ollama安装 ollama是一个开源的大型语言模型&#xff08;LLM&#xff09;本地化部署与管理工具&#xff0c;旨在简化在本地计算机上运行和管理大语言模型…...

Linux:vim快捷键

Linux打开vim默认第一个模式是&#xff1a;命令模式&#xff01; 命令模式快捷键操作&#xff1a; gg&#xff1a;光标快速定位到最开始 shift g G&#xff1a;光标快速定位到最结尾 n shift g n G&#xff1a;光标快速定位到第n行 shift 6 ^&#xff1a;当前行开始 …...

Unity 对象池技术

介绍 是什么&#xff1f; 在开始时初始化若干对象&#xff0c;将它们存到对象池中。需要使用的时候从对象池中取出&#xff0c;使用完后重新放回对象池中。 优点 可以避免频繁创建和销毁对象带来性能消耗。 适用场景 如果需要对某种对象进行频繁创建和销毁时&#xff0c;例…...

算法1-4 凌乱的yyy / 线段覆盖

题目描述 现在各大 oj 上有 n 个比赛&#xff0c;每个比赛的开始、结束的时间点是知道的。 yyy 认为&#xff0c;参加越多的比赛&#xff0c;noip 就能考的越好&#xff08;假的&#xff09;。 所以&#xff0c;他想知道他最多能参加几个比赛。 由于 yyy 是蒟蒻&#xff0c…...

【计网】数据链路层

数据链路层 3.1 数据链路层概述3.2 封装成帧3.3 差错检测3.4 可靠传输3.4.1 可靠传输的概念3.4.2 可靠传输的实现机制 - 停止等待协议3.4.3 可靠传输的实现机制 -回退N帧协议3.4.4 可靠传输的实现机制 -选择重传协议 3.5 点对点协议3.5.1 帧格式3.5.2 透明传输 3.6 媒体接入控制…...

javaweb自用笔记:Vue

Vue 什么是vue vue案例 1、引入vue.js文件 2、定义vue对象 3、定义vue接管的区域el 4、定义数据模型data 5、定义视图div 6、通过标签v-model来绑定数据模型 7、{{message}}直接将数据模型message展示出来 8、由于vue的双向数据绑定&#xff0c;当视图层标签input里的…...

CSS Overflow 属性详解

CSS Overflow 属性详解 在网页设计和开发中,CSS Overflow 属性是一个非常重要的特性,它决定了当内容超出其容器大小时应该如何处理。本文将详细介绍 CSS Overflow 属性的相关知识,包括其语法、作用、常用属性值以及一些实际应用场景。 1. CSS Overflow 属性概述 CSS Over…...

沃丰科技结合DeepSeek大模型技术落地与应用前后效果对比

技术突破&#xff1a;DeepSeek算法创新&#xff0c;显著降低了显存占用和推理成本。仅需少量标注数据即可提升推理能力。这种突破减少了对海量数据的依赖&#xff0c;削弱了数据垄断企业的优势&#xff01; 商业模式颠覆&#xff1a;DeepSeek选择完全开源模式&#xff0c;迫使…...

突破光学成像局限:全视野光学血管造影技术新进展

全视野光学血管造影&#xff08;FFOA&#xff09;作为一种实时、无创的成像技术&#xff0c;能够提取生物血液微循环信息&#xff0c;为深入探究生物组织的功能和病理变化提供关键数据。然而&#xff0c;传统FFOA成像方法受到光学镜头景深&#xff08;DOF&#xff09;的限制&am…...

2.反向传播机制简述——大模型开发深度学习理论基础

在深度学习开发中&#xff0c;反向传播机制是训练神经网络不可或缺的一部分。它让模型能够通过不断调整权重&#xff0c;从而将预测误差最小化。本文将从实际开发角度出发&#xff0c;简要介绍反向传播机制的核心概念、基本流程、在现代网络中的扩展&#xff0c;以及如何利用自…...

机器学习校招面经二

快手 机器学习算法 一、AUC&#xff08;Area Under the ROC Curve&#xff09;怎么计算&#xff1f;AUC接近1可能的原因是什么&#xff1f; 见【搜广推校招面经四】 AUC 是评估分类模型性能的重要指标&#xff0c;用于衡量模型在不同阈值下区分正负样本的能力。它是 ROC 曲线…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...