【Linux系统化学习】动静态库 | 软硬链接

目录

硬链接和软链接

硬链接

软链接 

动态库和静态库

静态库

静态库的生成

静态库的使用

将库打包和使用

动态库

动态库的生成

动态库的使用 

库搜索路径


硬链接和软链接

硬链接

上篇文章我们说到真正找到磁盘上的文件并不是文件名,而是inode。其实在Linux中可以让多个文件名对应同一个inode,这样的方式就是硬链接

指令:ln 

总结: 

  • 硬链接不是一个独立的文件 ,就是在指定目录内部的一组映射关系。相当于引用计数;当没有文件名和inode映射时表示该文件被真正的删除。

  • 硬连接的作用是允许一个文件拥有多个有效路径名,这样用户就可以建立硬连接到重要文件,以防止“误删”的功能。

注:硬链接只可以链接文件不可以链接目录;因为引入了对目录的硬连接就有可能在目录中引入循环,在目录遍历的时候系统就会陷入无限循环当中,这样导致无法定位到访问目录。但是我们的Linux系统可以硬链接目录;每个目录文件中含有两个隐藏文件,分别为当前目录和上级目录,当前目录隐藏文件就和当前目录硬链接。

软链接 

硬链接是通过inode引用另外一个文件,软链接是通过名字引用另外一个文件。

指令:ln -s

总结:

软连接是一个独立的文件,有独立的inode;软连接内容时指向目标文件的路径,类似于Windows的快捷方式


动态库和静态库

在之前的文章中我们提到过系统库,当时只是简单的讲解了下静态库和动态库的优缺点;这篇文章我们要从一个库的制作者和使用者来详细介绍第三方库的制作和使用。

  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚
  • 拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

静态库

我们以一个库的制作者的角度自己编写一个可以实现整数加减的库;就是将实现整数加减的两个函数声明和定义分开,声明放在头文件中,实现放在源文件中。

头文件

  1 #pragma once 2 #include<stdio.h>                                                        3 extern int Add(int,int);
 1 #pragma once 2 #include<stdio.h>                                                        3 extern int Sub(int,int);

源文件 

  1 #include"Add.h"2 int Add(int x,int y)3 {4     return x+y;                                                          5 }
  1 #include"Sub.h"2 int Sub(int x,int y)3 {4     return x-y;                                                          5 }

当我们以库的制作者的身份将库写好后;我们就以普通程序员的身份使用这个库编写简单的程序。

  1 #include"Add.h"2 #include"Sub.h"3 int main()4 {5     int x =10;6     int y=20;7     printf("%d + %d = %d\n",x,y,Add(x,y));8     printf("%d - %d = %d\n",x,y,Sub(x,y));                               9     return 0;10 }

第一种使用方法就是将我们自己编写的源代码和库的源代码一起编译链接形成一个可执行程序即可。

但是这种使用方法我们要拿到库的源代码;再将库的每个源代码和我们的源代码一起预处理、编译、链接形成可执行程序。对于我们这种小库可能没什么影响,对于一些大的库源文件很多,每个源文件都进行这三部操作的话,很是浪费时间。

静态库的生成

对于上面的问题我们可以很好的解决;不是库的源文件浪费时间么,同时作为库的制作者我们也不想将我们的源代码公开,那我们可以将我们的库先编译成为二进制文件(.O)文件,将二进制文件和库使用者的二进制文件进行连接即可形成可执行程序

  makefile1 test:Add.o Sub.o testmain.o2     gcc -o $@ $^3 %.o:%.c4     gcc -c $<  

但是当我们库很大源文件很多时,形成的二进制文件也特别多;要是我们给库使用者二进制文件少给一个呢?

当我们想要这个库时候是不是只需要将我们的源文件编译成.o文件和库文件进行链接即可。因此我们可以将库的源文件编译成.o文件打包交给程序员即可。

    makefile    static-lib=libmymath.a2 $(static-lib):Add.o Sub.o3     ar -rc $@ $^                                                         6 %.o:%.c7     gcc -c $<8 .PHONY:clean9 clean:10     rm -rf *.o test

指令:ar -rc libmymath.a add.o sub.o
ar是gnu归档工具,rc表示(replace and create)

当我们库的源文件很多时,我们可以使用makefile,将我们的源代码自动生成二进制文件,再将我们的二进制文件全部形成我们的静态库。这里我们库的源文件很少,我就直接给大家手动生成。

通过上面的操作我们就可以将库的源文件生成二进制文件,进行生成静态库。

静态库的使用

将生成好的二进制文件和头文件拷贝到,我们的使用者编写的源代码下就可以使用库了。但是我们在使用静态库时还有很多小细节要注意。

将静态库和我们的源文件进行链接时首先要表用链接库的名称,和静态库的路径。其中库的名称是去掉后缀(.a)和lib。

  • -l 静态库的名称   代表我们链接哪一个静态库
  • -L 路径    代表所要链接静态库的所在路径

将库打包和使用

上面只是进行了二进制文件的打包当我们库源文件很多时,头文件也很多;因此我们可以将头文件和二进制文件分开存储在一个目录中打包交给使用的程序员。这里我们就不打包了,我们只将其放在同一个目录中使用。

    static-lib=libmymath.a2 $(static-lib):Add.o Sub.o3     ar -rc $@ $^6 %.o:%.c7     gcc -c $<8 .PHONY:output9 output:10     mkdir -p mymath_lib/include11     mkdir -p mymath_lib/lib 12     cp -f *.h mymath_lib/include13     cp -f *.a mymath_lib/lib14 .PHONY:clean15 clean:16     rm -rf *.o test mymath_lib

但是打包好的头文件和二进制文件在统一目录下,而我们的源文件并不在统一目录下,因此我们在使用的时候还要加上一些选项。

注:头文件的查找在当前目录下或者指定目录下查找,因此我们加上头文件的路径。

-I 头文件路径

 

动态库

动态库的生成

动态库也是将所有的的源文件形成二进制文件文件生成的;但是和动态库的生成方式和使用方式略有差异。 

注意:动态库的生成是使用gcc编译器来完成的,因此比较重要

makefile1 dy-lib=libmymath.so 2 $(dy-lib):Add.o Sub.o3     gcc -shared -o $@ $^4 %.o:%.c5     gcc -fPIC -c $<6 .PHONY:output7 output:8     mkdir -p mymath_lib/include9     mkdir -p mymath_lib/lib 10     cp -f *.h mymath_lib/include11     cp -f *.a mymath_lib/lib12 .PHONY:clean13 clean:14     rm -rf *.o *.so mymath_lib                                
~                                   

  • shared: 表示生成共享库格式
  • fPIC:产生位置无关码(position independent code)
  • 库名规则:libxxx.so

有了上面静态库的生成,静态库的生成我们就不过多赘述,只是生成动态库执行的选项不一样而已。

动态库的使用 

动态库的使用也是有很多的小细节,使用不当也会产生找不到动态库或者找不到头文件的问题。 

就像下面我们直接使用使用静态库的方法使用动态库,系统还是找不到我们的库在哪里。 

 

原因:

静态库是直接和我们的可执行程序链接在一起的,在连接的时候告诉我们的编译器我们库的路径编译器就可以找到。但是对于动态库不是链接在可执行程序中,可执行程序和库必须都加载到内存中,我们告诉了gcc编译器我们的库在哪里,但是操作系统要将我们的库加载到内存中,操作系统却不知道我们的库在哪里,系统默认找不到。因此我们要解决系统找不到我们库的问题。

库搜索路径

方法一:将头文件和库文件安装到系统中 

  • /usr/include
  • /lib64

在我们这两个系统路径下分别存放着库的头文件和二进制文件,我们可以将我们的二进制文件和头文件分别拷贝到上面的系统路径下即可。

方法二:建立一个软链接

在生成可执行程序的目录下建立一个库的软链接即可。

方法三:修改环境变量

LD_LIBRARY_PATH

执行我们的可执行程序系统不仅会在指定的路径下寻找我们的动态库,还会在一个环境变量中寻找。Linux中存在这样一个环境变量记录着动态库的存储路径。我们可以将我们的动态库添加到这一环境变量中即可。

注意

当我们退出我们的云服务器,重新登录后添加的环境变量就将会重置。 

方法四:更改配置文件

Linux下含有一个文件夹其中包含有关动态库加载的配置文件,里面只含有一个路径。我们可以在其目录下创建一个相同格式的空白文件,再将我们库的路径填入其中保存即可。


今天对Linux下动静态库的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!!  

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

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

相关文章

CF1731D Valiant‘s New Map 题解

文章目录 CF1731D Valiants New Map 题解Valiants New Map题面翻译题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示算法&#xff1a;二分二维前缀和代码&#xff1a; CF1731D Valiant’s New Map 题解 link Valiant’s New Map 题面翻译 给定一个带权值的 n …

Adobe Ai下载安装免费(矢量图形编辑软件Ai安装包下载2024【Windows版】)

Adobe全家桶下载方式 Ae下载 Pr下载 Ai下载 将持续更新~ 文章目录 Adobe全家桶下载方式Ai下载方式【点我获取下载链接】我们的网站一、Ai简介二、链接内容包含1.Ai软件 声明 Ai下载方式【点我获取下载链接】 百度网盘下载&#xff1a;百度网盘下载方式夸克网盘下载&#xff…

Day 6.文件属性和权限的获取

时间获取 1.time time_t time(time_t *tloc); 功能&#xff1a; 返回1907-1-1到现在的秒数&#xff08;格林威治时间&#xff09; 参数&#xff1a; tloc&#xff1a;存放秒数空间的首地址 返回值&#xff1a; 成功返回秒数 失败返回-1 2.localtime struct tm *loca…

Python入门:常用模块—logging模块

logging日志的分级&#xff1a; debug(),info(),warning(),error(),critical() 5个级别 最简单用法 1 2 3 4 import logging logging.warning("user [mike] attempted wrong password more than 3 times") logging.critical("server is down") 输出&…

Day49 647 回文子串 516 最长回文子序列

647 回文子串 给定一个字符串&#xff0c;你的任务是计算这个字符串中有多少个回文子串。 具有不同开始位置或结束位置的子串&#xff0c;即使是由相同的字符组成&#xff0c;也会被视作不同的子串。 方法一&#xff1a;动态规划&#xff1a; 采用一个二维的dp数组&#xf…

普中51单片机学习(二)

51单片机介绍 所需基础知识 基础数模电知识&#xff0c;简单的C语言。 PS&#xff1a;如果有不懂的直接通义千问。。。 什么是单片机 在一片集成电路芯片上集成微处理器、存储器、I/O接口电路&#xff0c;从而构成了单芯片微型计算机&#xff0c;即单片机。 学习方法 多实…

Sqoop 入门基础

简介 Sqoop&#xff08;SQL to Hadoop&#xff09;是一个开源工具&#xff0c;用于在关系型数据库和Hadoop之间传输数据。它提供了一种快速高效的方式&#xff0c;将数据从关系型数据库导入到Hadoop集群进行分析&#xff0c;并支持将Hadoop集群中的数据导出到关系型数据库中。本…

【编程】C++语言编程规范-2

编程实践 结合C Effective系列参考树、尤其是工程经验教训的总结。 并发 除非必要&#xff0c;尽量少用线程。多线程编程要守护好内存&#xff0c;使用atomic、mutex、condition variable、future、semaphore、latch、barrier等同步机制避免数据竞争。尽量缩小临界区&#x…

智慧社区管理系统:构建未来的生活模式

在这个信息化、智能化的时代&#xff0c;我们期待的不再是简单的居住空间&#xff0c;而是一个集安全、便捷、舒适、环保于一体的智能化社区。为此&#xff0c;我们推出了全新的智慧社区管理系统&#xff0c;旨在将先进的科技力量引入社区管理&#xff0c;为居民提供更优质的生…

OpenProject + Rocky8安装

文章目录 1、概要2、整体架构流程3、准备4、安装5、openproject 配置5.1、第一步&#xff1a;OpenProject 版本选择5.2、第二步&#xff1a;PostgreSQL 支持5.3、第三步&#xff1a;Apache2 Web 服务器支持5.4、第四步&#xff1a;hostname 支持5.5、 第五步&#xff1a;服务器…

从零学算法172

172.给定一个整数 n &#xff0c;返回 n! 结果中尾随零的数量。 提示 n! n * (n - 1) * (n - 2) * … * 3 * 2 * 1 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;0 解释&#xff1a;3! 6 &#xff0c;不含尾随 0 示例 2&#xff1a; 输入&#xff1a;n 5 输出&…

【Docker】Docker存储卷

文章目录 一、什么是存储卷二、为什么需要存储卷三、存储卷分类四、管理卷Volume创建卷方式一&#xff1a;Volume 命令操作方式二&#xff1a;-v 或者--mount 指定方式三&#xff1a;Dockerfile 匿名卷 操作案例Docker 命令创建管理卷Docker -v 创建管理卷Docker mount 创建管理…

懒加载实践记录

1.原理 懒加载的原理是通过监听用户的浏览行为&#xff0c;当用户滚动到可视区域内时&#xff0c;再进行资源的加载。这样可以避免一次性加载过多的资源&#xff0c;从而减少页面的加载时间和带宽消耗。 2.主要使用场景 懒加载适用于图片较多&#xff0c;页面列表较长(长列表)…

Linux——常用特殊符号介绍

1、# 井号 (comments) 这几乎是个满场都有的符号&#xff0c;除了先前已经提过的"第一行" #!/bin/bash 井号也常出现在一行的开头&#xff0c;或者位于完整指令之后&#xff0c;这类情况表示符号后面的是注解文字&#xff0c;不会被执行。 # This line is comments.…

unity学习(32)——跳转到角色选择界面(父子类问题)

新问题 应该是两个脚本之间缺少继承关系 its children 解决起来很简单&#xff0c;把ResceneScript也绑到canvas上就可以了 。 此时&#xff0c;在账号密码正确的情况下&#xff0c;是可以完成场景切换。 对应的代码如下&#xff1a; TMP_Text d GameObject.FindWithTag(&…

嵌入式Linux学习DAY20

文件io 文件io和标准io的区别&#xff1a; 1.标准io是库函数&#xff0c;是对系统调用的封装 2.文件io是系统的调用&#xff0c;是Linux内核中的函数接口 3.标准io是有缓存的 4.文件io是没有缓存的 操作步骤 打开->读写->关闭 打开文件&#xff1a;open 功能&am…

了解不同颜色油封的用途

在机械领域&#xff0c;油封是保证各种设备平稳运行的关键部件。为什么油封会有很多颜色。本文旨在阐明不同颜色油封的用途及其意义。 油封有多种颜色&#xff0c;包括黑色、棕色、绿色和蓝色等。乍一看&#xff0c;这些颜色似乎只是一种审美选择。然而&#xff0c;它们有更实…

接口测试(postman/jmeter)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、什么是接口测试 通常做的接口测试指的是系统对外的接口&am…

Window部署Nacos

Nacos 现在压缩包解压后&#xff0c;修改conf/application.properties 文件 取消注释&#xff0c;修改mysql连接方式 节点nacos.core.auth.enabled 改成true 设置节点nacos.core.auth.server.identity.key、nacos.core.auth.server.identity.value 设置secret秘钥&#xff0c;…

十大常见web漏洞及防范

十大常见web漏洞 一、SQL注入漏洞 SQL注入攻击&#xff08;SQL Injection&#xff09;&#xff0c;简称注入攻击、SQL注入&#xff0c;被广泛用于非法获取网站控制权&#xff0c;是发生在应用程序的数据库层上的安全漏洞。在设计程序&#xff0c;忽略了对输入字符串中夹带的S…