【Linux】基础IO —— 下(实现动静态库)

article/2025/10/31 2:45:47

🎇Linux:基础IO


  • 博客主页:一起去看日落吗
  • 分享博主的在Linux中学习到的知识和遇到的问题
  • 博主的能力有限,出现错误希望大家不吝赐教
  • 分享给大家一句我很喜欢的话: 看似不起波澜的日复一日,一定会在某一天让你看见坚持的意义,祝我们都能在鸡零狗碎里找到闪闪的快乐🌿🌞🐾。

在这里插入图片描述

☁️ ❄️ ⛄️


目录

  • ⛄️1. Linux动静态库
    • ❄️ 1.1 认识动静态库
    • ❄️ 1.2 动态库
    • ❄️ 1.3 静态库
  • ⛄️2. 静态库的打包与使用
    • ❄️ 2.1 静态库的打包
    • ❄️ 2.2 静态库的使用
  • ⛄️3. 动态库的使用与打包
    • ❄️ 3.1 动态库的打包
    • ❄️ 3.2 动态库的使用

⛄️1. Linux动静态库

❄️ 1.1 认识动静态库

#include<stdio.h>int main()
{printf("hello byh\n");return 0;
}

这段代码的运行结果大家一眼就可以看出来了
请添加图片描述
在Linux下我们可以通过ldd指令来查看一个可执行程序所依赖的库文件

ldd [某可执行程序]  

在这里插入图片描述
这里的libc.so.6就是当前可执行程序所依赖的库文件,我们通过ls命令查看后发现libc.so.6它其实就是一个软链接。

在这里插入图片描述这就是我们使用的C标准库,它的大小是 2156592 这么些。我们使用的标准IO、字符串操作和整数数学函数所谓的这些的库,也不过是安装在系统中的文件罢了。

这个时候我就有一个问题:那么我们怎么知道这个库是一个动态库还是静态库呢?

上面说了libc.so.6它是一个软链接,而该软链接的源文件就是libc-2.17.so。因此我们可以通过file+文件名来查看一下libc-2.17.so的文件类型

file /lib64/libc-2.17.so

在这里插入图片描述
可以看到libc-2.17.so它其实是一个动态库

注意:

  • 在Linux下,以.so为后缀的文件是动态库,以.a为后缀的文件是静态库
  • 在Windows下,以.dll为后缀的文件是动态库,以.lib为后缀的文件是静态库

在Linux下,libbyh.so,我们去掉前缀lib,去掉后缀.so,剩下的就是该动静态库的库名了。

在Linux下,gcc/g++编译器默认采用的是动态链接,若是想采用静态链接的话,我们需要在gcc/g++后面带上一个-static选项即可。

大家在使用gcc/g++命令带这个选项的时候可能会由于当前云服务器上面没有下载静态库而导致出错,因此我们需要先使用下面这两条命令分别下载gcc/g++静态库之后再去进行静态链接,这样的话就不会出错了。

yum install glibc-static
yum install glibc-static libstdc++-static

在这里插入图片描述我们生成一个静态链接的可执行程序,我们可以看到静态链接生成的可执行程序文件比动态链接生成的可执行程序的文件大小要大很多,将近大了100倍。由于静态链接所生成的可执行程序它不依赖第三方库,因此当我们通过ldd指令去查看静态链接生成的可执行程序所依赖的库文件时就会出现下面这一幕:

请添加图片描述

当我们用file命令分别查看这个可执行程序的文件类型时,我们可以看到它是静态链接的。

在这里插入图片描述


❄️ 1.2 动态库

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

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

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

在这里插入图片描述

优点:

  • 使用动态库生成的可执行程序体积比较小,节省资源。当多个可执行程序同时运行时,若是要使用同一个库,库文件会通过进程地址空间进行共享,内存中不会存在重复代码。

缺点:

  • 比较依赖第三方库。

❄️ 1.3 静态库

静态库是在程序编译链接的时候将库中的代码拷贝到可执行程序里面,生成的可执行程序就不再需要依赖第三方库,同时生成的可执行程序的体积比较大。

优点:

  • 使用静态库生成的可执行程序,它不需要依赖于第三方库,即使没有第三方库它也可以独立运行,可移植性高。

缺点:

  • 生成的可执行程序体积比较大,比较占资源。 当多个静态链接生成的可执行程序使用同一个库时,内存中会存在大量重复的代码。

⛄️2. 静态库的打包与使用

❄️ 2.1 静态库的打包

静态库打包的本质:把你的代码生成的二进制.o文件进行打包。

下面我们用简单的加法和减法来做演示

my_add.h

#pragma once
#include<stdio.h>int my_add(int a,int b);

my_add.c

#include"my_add.h"int my_add(int a,int b)
{return a+b;
}

my_sub.h

#pragma once
#include<stdio.h>int my_sub(int a,int b);

my_sub.c

#include"my_sub.h"int my_sub(int a,int b)
{return a-b;
}

下面我们来将这四个文件进行打包然后生成一个静态库

  • 第一步

将所有的源文件变成对应的.o目标文件

在这里插入图片描述


  • 第二步

使用ar命令将所有的目标文件打包生成静态库

在这里插入图片描述

注意:

ar命令是gnu的归档工具,它常用于将目标文件打包为静态库,ar命令中的-r选项与-c选项分别代表的是repalce和creat。

  • -r(replace):若静态库文件当中的目标文件有更新,则用新的目标文件替换旧的目标文件。
  • -c(creat):建立静态库文件。
  • -t:列出静态库重点文件
  • -v(verbose):详细信息

  • 第三步

将生成的静态库文件与目标文件对应的头文件组织起来

当我们将我们自己的库给别人使用的时候,我们需要创建两个目录,一个用来存放所有的头文件,一个用来存放静态库文件。

因此,我们将myadd.h与mysub.h这两个头文件放到include这个目录下。将静态库文件放到lib这个目录下。然后将这两个目录都放到mylib这个目录下,此时我们若是向把我们自己的库给别人使用,我们只需要将mylib这个文件发给别人就可以了。

在这里插入图片描述

注意:

Mac下没有tree命令,而window下是有的,需要下载

sudo yum -y install tree

❄️ 2.2 静态库的使用

静态库生成好了之后,我们就来尝试着使用以下这个静态库吧。

我们首先创建一个test.c文件,然后写一段简单的代码用一下加法函数

text.c

#include"my_add.h"
int main()
{int x = 10;int y = 20;printf("add: %d\n",my_add(x,y));return 0;
}

Makefile

text:text.cgcc -o $@ $^ -static.PHONY:clean
clean:rm -f text
  • 方法一

使用gcc选项

在这里插入图片描述我们发现居然出错了,我们打包好的静态库和头文件不就在当前目录下嘛,为什么它这里却又说找不到呢?

这是因为编译器它并不知道你所包含的my_add.h头文件在哪里,所以我们需要指定头文件的搜索路径。

因此我们需要在makefile里面的gcc后面带一个选项就可以指定头文件的搜索路径了

-I:指定头文件的搜索路径

在这里插入图片描述

修改完之后我们重新make一下

在这里插入图片描述

我们发现又出错误了

这是因为你只是告诉了编译器库文件的搜索路径在哪里,但是你并没有告诉你要去链接哪一个库,假如说这个库文件里面有很多个库,那编译器它又怎么知道你想要去链接哪个库呢。

这是因为头文件my_add.h里面只有加法函数的声明,并没有函数的定义,因此我们还需要指定库文件的搜索路径。

因此我们只需要在makefile里面的gcc后面带一个选项就可以指定库文件的搜索路径了

-L:指定库文件搜索路径

在这里插入图片描述

我们接着再来make一下

在这里插入图片描述

我们发现又出错误了

这是因为你只是告诉了编译器库文件的搜索路径在哪里,但是你并没有告诉你要去链接哪一个库,假如说这个库文件里面有很多个库,那编译器它又怎么知道你想要去链接哪个库呢?

所以我们还需要指定一下我们需要链接库文件中的哪一个库。

因此我们需要在makefile里面的gcc后面再带一个选项去指明我们想要链接库文件中的哪一个库。

l:指明想要链接库文件中的哪一个库

在这里插入图片描述

我们再来make一下看看结果

在这里插入图片描述
最终我们得到了我们想要的运行结果。

注意: 所有的库和头文件只有在当前路径下能够被直接找到,如果当前路径下还包了目录,那么你就需要指明你的搜索路径才行。

  • 方法二

将头文件和库文件放到系统路径下

如果我们不指定搜索路径的话,编译器它就找不到我们的头文件和库文件,除了上面指定搜索路径的法子我们还可以将我们的头文件和库文件放到系统路径下,这样的话编译器就能够找到了。

尽管使用这种方式我们不需要指定头文件的搜索路径和库文件的搜索路径,但是我们还是要告诉编译器我们链接库文件的哪个库。

虽然说这种方法相较于第一种方法而言会简单一点,但是我不建议你使用这种方法,原因有两个:

  • 将我们的头文件和库文件放到系统路径下,这样做有可能会对系统文件造成污染
  • 使用第一种方法可以帮你熟悉gcc命令,同时使用第一种方法虽然麻烦但是不会对系统文件造成污染。

⛄️3. 动态库的使用与打包

❄️ 3.1 动态库的打包

我们上面学了静态库的打包和使用之后,接下来我们再来学习动态库的打包和使用就会容易很多了。因此动静态库的打包基本类似。下面我们继续使用这四个文件来给大家展示动态库的打包和使用

在这里插入图片描述

  • 第一步

让所有的源文件生成对应的.o目标文件

fPIC 产生位置无关码(position independent code)

在这里插入图片描述


  • 第二步

将目标文件打包生成动态库

在这里插入图片描述

然后我们来make一下生成对应的目标文件和动态库:

在这里插入图片描述


  • 第三步

将头文件和我们生成的动态库组织起来

这里我们换一种方式来将它们两个组织起来,我们在Makefile里面编写一段代码,通过 发布 然后将他们给组织起来。

在这里插入图片描述

下面我们来make output一下,通过发布将头文件和动态库给组织起来:

在这里插入图片描述

此时我们的动态库和头文件就已经打包完毕了,如果后面别人想要用我们的这个库,我们只需要把mylib这个文件给别人就可以了。


❄️ 3.2 动态库的使用

上面我们的动态库打包好之后,我们就来使用一下我们打包好的动态库吧,下面我们依然使用test.c文件来为大家演示动态库的使用

text.c

#include"my_add.h"
#include"my_sub.h"int main()
{int a = 20;int b = 10;printf("add: %d\n",myadd(a,b));printf("sub: %d\n",mysub(a,b));return 0;
}

Makefile:

test:text.cgcc -o $@ $^ -I./mylib/include -L./mylib/lib  -lmy_math    .PHONY:clean
clean:rm -f test 

请添加图片描述
可以看到我们这里执行可执行程序的时候出错了,这个时候我就比较好奇了:我明明已经指定头文件的搜索路径,指定库文件的搜索路径,以及我们要链接库文件中的哪一个,为什么我们这里还是会报错呢?

这是因为你只是告诉了编译器,你并没有告诉操作系统。不要忘了链接动态库的时候是在程序运行的时候链接的。

可以看到当我们用ldd命令查看test可执行程序的时候,发现找不到这个动态库

请添加图片描述

那么问题又来了:我们应该如何解决呢?

  • 方法一

与静态库使用的第二种方法类似,我们将动态库拷到系统路径下。

  • 方法二

更改LD_LIBRARY_PATH

LD_LIBRARY_PATH是程序运行时帮我们找动态库的路径的,因此我们将该动态库所在目录路径添加到LD_LIBRARY这个环境变量中就可以了

# export LD_LIBRARY_PATH=路径

请添加图片描述
可以看到我们现在再使用ldd命令的时候就可以找到该动态库了。

下面我们来执行一下这个可执行程序吧

请添加图片描述



http://chatgpt.dhexx.cn/article/b1hQhZbN.shtml

相关文章

【Linux】第九章 动态库和静态库(生成原理+生成和使用+动态链接)

&#x1f3c6;个人主页&#xff1a;企鹅不叫的博客 ​ &#x1f308;专栏 C语言初阶和进阶C项目Leetcode刷题初阶数据结构与算法C初阶和进阶《深入理解计算机操作系统》《高质量C/C编程》Linux ⭐️ 博主码云gitee链接&#xff1a;代码仓库地址 ⚡若有帮助可以【关注点赞收藏】…

Linux——自动化编译(make的使用)、库文件(静态库和共享库的使用)

一、make的使用&#xff08;自动化编译&#xff09; make是Linux上的工程管理工具&#xff0c;可以实现自动化编译&#xff1b;make可以提高我们的编译效率。 1.安装make 命令&#xff1a;sudo apt install make 2.make的用法 &#xff08;1&#xff09;创建makefile文件&am…

rpc系列-ZooKeeper

一.简介 Zookeeper是一个分布式协调服务&#xff0c;就是为用户的分布式应用程序提供协调服务。 Zookeeper本身就是一个分布式程序&#xff08;只要有半数以上节点存活&#xff0c;zk就能正常服务&#xff09;。 Zookeeper所提供的服务涵盖&#xff1a;主从协调、服务器节点…

HBase 一文读懂

本文基于《尚硅谷大数据技术之HBase》编写。 HBase 简介 HBase定义 HBase是一种分布式、可扩展、支持海量数据存储的NoSQL数据库。 HBase数据模型 HBase的数据模型同关系型数据库&#xff08;RDMS&#xff09;很类似&#xff0c;数据存储在一张表中&#xff0c;有行有列。但从H…

Zookeeper学习

文章目录 今日目标apache zookeeperzookeeper的概念分布式和集群的理解zookeeper的集群架构和角色zookeeper的5大特性部署zookeeper集群环境计算机集群的安装部署三台节点&#xff08;克隆两台&#xff09;配置节点内存和CPUzookeeper安装 zookeeper的数据模型zookeeper的节点类…

Redission和Zookeeper分别实现分布式锁

Redission和Zookeeper分别实现分布式锁&#xff08;windows&#xff09; 1、Redission实现分布式事务 1.1 前提准备 下载好nginx&#xff08;windows版本&#xff09;下载好Jmeter&#xff08;模仿高并发&#xff09;下载好redis&#xff08;windows版&#xff09; 1.2 代码…

Zookeeper 客户端之基本操作指令

ZooKeeper命令行工具类似于Linux的shell环境&#xff0c;不过功能肯定不及shell啦&#xff0c;但是使用它我们可以简单的对ZooKeeper进行访问&#xff0c;数据创建&#xff0c;数据修改等操作. 命令行工具的一些简单操作如下&#xff1a; zkCli.sh客户端连接命令 ls 与 ls2 命…

kafka内置zookeeper启动失败报错INFO ZooKeeper audit is disabled. (org.apache.zookeeper.audit.ZKAuditProvider)

kafka内置zookeeper启动失败报错INFO ZooKeeper audit is disabled.(org.apache.zookeeper.audit.ZKAuditProvider)2022年新版win10安装kafka 安装配置kafka&#xff0c;在启动zookeeper时报错ZooKeeper audit is disabled 原因分析&#xff1a; 寻找资料发现是zookeeper设置参…

zookeeper日志及快照清理操作

事务日志可视化转换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #!/bin/sh # scriptname: zkLog2txt.sh # zookeeper事务日志为二进制格式&#xff0c;使用LogFormatter方法转换为可阅读的日志 if [ -z "$1" -o "$1" "-h&quo…

【RPC】注册中心实现方案之ZooKeeper

文章目录 ZooKeeper一致性协议&#xff1a;ZAB ZooKeeper ZooKeeper是一个开源的分布式协调服务&#xff0c;它可以用来协调和同步多服务器之间的状态。 ZooKeeper 可以作为微服务架构中注册中心的选型&#xff0c;它最需要被关心的也是数据模型和一致性协议。数据模型关乎服…

Linux 搭建zookpeer集群和配置

zookpeer和JDK1.8下载地址 下载地址&#xff1a;zookpeer和jdk1.8 提取码&#xff1a;w189 解压以及配置zookpeer tar -zxvf zookeeper-3.4.6.tar.gz tar -zxvf jdk-8u144-linux-x64.tar.gz 基本参数配置 参数描述clientPort主要定义客户端连接zookeeper server的端口&…

hadoop-zookeeper的详细介绍以及安装配置步骤

一、zookeeper的介绍 ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务&#xff0c;是Google的Chubby一个开源的实现&#xff0c;是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件&#xff0c;提供的功能包括&#xff1a;配置维护、…

k8s-7: kafka+zookeeper的单节点与集群的持久化

之前在k8s环境中有这个需求&#xff0c;看了好多的文档&#xff0c;都有坑&#xff0c;踩了一边总结一下&#xff0c;需要的朋友可自取 一、单节点部署 建议开发环境使用&#xff0c;且此处采用动态挂载的&#xff0c;生产不建议 1、安装zk cat > zk.yaml <<EOF a…

Docker 安装Zookeeper

第一步&#xff1a;查看本地镜像和检索拉取Zookeeper 镜像 # 查看本地镜像 docker images # 检索ZooKeeper 镜像 docker search zookeeper # 拉取ZooKeeper镜像最新版本 docker pull zookeeper:latest [rootlocalhost ~]# docker images REPOSITORY TAG …

mac pro m1:搭建zookeeper集群并设置开机自启

0. 引言 之前我们讲解过搭建zookeeper单节点&#xff0c;但在实际生产中&#xff0c;为了保证服务高可用&#xff0c;通常我们是采用集群模式。所以本次我们来实操集群模式的搭建 1. zk集群模式 zk可以作为注册中心和配置中心&#xff0c;常用在微服务各类组件的多节点服务治…

一款实用的数据恢复软件—zook data recovery wizard

zook data recovery wizard是RecoveryTools下的一款子品牌&#xff0c;同时也是一款功能实用的数据恢复软件&#xff0c;该软件可以从Windows中恢复已删除&#xff0c;损坏&#xff0c;格式化和丢失的数据&#xff0c;能够支持从驱动器&#xff0c;SD卡&#xff0c;硬盘&#x…

zook 报错 Unable to read additional data from server sessionid 0x0

zook报错启动报错&#xff1a; 2017-09-25 18:33:46,913 - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread1183] - Unable to read additional data from server sessionid 0x0, likely server has closed socket, closing socket connection and attempting r…

hadoop大数据集群搭设(hadoop+zook+HBase+hive)百分百成功

hadoop大数据集群搭设 前言所需软件虚拟机准备工作一、Jdk安装二、安装zookeeper三、HBase安装四、mysql安装配置五、安装hive 前言 经过长时间的测试总结出在目前集群搭建最稳定的步骤是&#xff1a; 至少我按这个过程基本0失误&#xff0c;且初始化次数最少。当然也可以尝试…

zookeeper客户端命令(三)

zookeeper客户端命令&#xff08;三&#xff09; 问题背景zookeeper分布式技术基本概念&#xff08;一&#xff09;zookeeper单机及集群部署&#xff0c;附安装包下载&#xff08;二&#xff09;zookeeper客户端命令&#xff08;三&#xff09; zook客户端指令节点创建测试集群…

Zookper集群搭建

&#x1f345;程序员小王的博客&#xff1a;程序员小王的博客 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 如有编辑错误联系作者&#xff0c;如果有比较好的文章欢迎分享给我&#xff0c;我会取其精华去其糟粕 一、搭建zookper集群前的准备…