【Linux】软硬链接与动静态库

news2024/12/24 9:10:20

环境:centos7.6,腾讯云服务器
Linux文章都放在了专栏:【 Linux 】欢迎支持订阅 🌹

相关文章:

【Linux】动静态库以及动静态链接

【Linux】基础IO_文件系统


软硬链接

软链接

我们知道,每一个文件都会有自己的inode编号,我们可以通过如下指令来查看:

ls -l -i

 我们发现,每一个不同文件的inode编号都不相同,所以inode可以说是用来标识文件的标识符。接下来,我们通过下面指令来给mysoft文件,创建软链接:

 ln -s mysoft mysoft-s

 我们发现,创建出来的软链接文件的inode编号与源文件并不相同,并且,软链接文件的大小远远小于源文件的大小。实际上,软链接又称为符号链接,软链接文件是一个独立的文件有自己的inode属性以及内容软链接文件的内容就是只包含了源文件的路径名称。因此大小要比源文件要小很多。这就类似于Windows下创建的快捷方式文件。

当然,假如我们将源文件删除或者改变源文件路径后,那么软链接文件也就运行不了,因为软链接文件内仅仅只是源文件所在的路径,当源文件不在时,软链接文件也就“失效了”。如下所示:

 硬链接

接下来我们来看硬链接,我们可以通过下面命令给mylink文件创建硬链接:

ln mylink mylink-h

我们发现,创建出来的硬链接文件不管是大小,还是inode编号都与源文件相同,并且那个数字也从1变成了2。可以看出来,硬链接代表的意义就是给源文件起一个“别名”,也就是说,虽然它们名字不同,但代表的都是同一个文件,因为它们的inode编号相同!。而这个数字2,就是用来统计一个文件究竟有几个“别名”。因此这里变成了2。

当然,假如此时我们将源文件的路径给更改,并不会发生什么影响,但是假如我们将源文件给删除。我们会发现,那个数字就会由2变成1,但依然可以运行。

接下来我们看一个现象:为什么目录文件硬链接数为2?

 答案是很简单,因为每一个目录文件,即使是个空目录,里面也一定有如下内容:当前路径文件.和上级路径文件..。

 当然,假如我们在B目录文件下再建立一个新的路径文件,那么B的硬链接数就会由2变成3,因为新的路径文件下都会有一个..文件,..标识上级路径,也就是B,因此B的硬链接数会由2变3。

这里有一点需要注意:我们可以给普通文件创建硬链接,但不能给目录文件创建硬链接,因为假如能给目录文件建立硬链接,就容易发生环路路径问题。

 软硬链接的区别

  1. 软链接又称为符号链接,是一个独立的文件,有单独的inode编号,该文件的内容为目标文件的路径。
  2. 硬链接是将不同的文件名关联到同一个inode节点,名字不同,但都是指同一个文件。
  3. 软链接可以给目录创建,但硬链接不可以给目录创建
  4. 删除原目标文件后,软链接文件会收到影响,会“失效”,但硬链接文件不受影响,依然可以正常运行,仅仅只是硬链接数-1。
  5. 硬链接的文件属性类型与原文件保持一致,而软链接文件的属性类型为l,l表示链接文件
  6. 软链接的大小很小,硬链接的大小与原目标文件一致,因为硬链接文件本身就是原目标文件的“别名”。

动静态库

什么是库文件?

我们在编写C/C++代码时,实际上一直都在用库(c/c++标准库),在编写代码时,有很多库函数诸如printf等,我们为什么能直接拿来用呢?是因为我们包含了各自对应的头文件,而头文件的内容包含了该函数的声明,具体的实现方法则在库文件中,在链接阶段,我们经过编译后的.o文件会与库文件进行合并,最终形成可执行程序。

因此,可以这么来说:库文件中提供函数的实现方法,而头文件中提供函数说明。两者配套使用。实际上,库其实就是大量方法文件形成的.o文件的集合

为什么要存在库?

库的存在就是为了提高开发效率,举个例子,假如没有c/c++标准库,我们在写代码时就要手动将printf、cout等高频函数的实现方法进行编写,这样就大大减少了我们的开发效率。

而且假如在日常开发中,假设别人想要使用我们实现的一些接口,但是我们又不想让别人看到我们是如何实现的,此时我们就可以将接口的实现打包成一个库,然后直接将库文件和对应头文件发送给对方即可。

库又分为动态库和静态库,两者的优缺点在之前的文章已经详细讲解<<点击跳转>>,这里主要讲如何库的使用和原理。

如何制作和使用第三方库

第一方库:语言提供的库(如c/c++标准库)

第二方库:操作系统提供

第三方库:other提供,比如我们接下来自己制作的动静态库

静态库的打包

静态库的打包主要分为两个步骤:

  1. 将存放方法的源文件进行编译,编译后(含预处理--编译--汇编)生成.o为后缀的可重定位二进制目标文件。(gcc -c)
  2. 将所有的.o文件使用ar -rc指令,进行打包形成静态库。
  3. 将静态库与头文件压缩后发送给他人即可供他人使用

这里我简单举个例子:

假如我自己写了一个Add和Sub接口的实现,然后其他人想直接用我们的接口,此时我们想在不将方法的具体实现暴露出来,仅仅是将接口的功能给他人使用,此时我们就可以打包成库,发送给别人即可。如下图:

第一步:使用g++ -c的指令,将方法实现的源文件进行编译后生成.o结尾的可重定位二进制文件:

  第二步:使用ar -rc 指令将所有的.o文件进行打包

注意:argnu归档工具,通常用指令ar -rc来进行静态库打包。而ar -tv指令则可以查看静态库的内容。如下:

 接下来,我们再将所有的头文件都放在同一个文件下,如下所示:

第三步:使用tar指令将库文件与头文件进行压缩,然后发送给其他人 使用即可

静态库的使用

 此时我们切换身份,我们作为otherPeople,我们想要使用这个静态库,该如何使用呢?

第三方库的使用规则

首先,任何第三方库的使用,必须在编译时要标注三个要素:库所在的路径、对应头文件的路径、要链接的库名(库名需要去掉前缀与后缀)。

第一种方式使用静态库:编译时手动指定

gcc/g++编译选项含义
-L指定库所在的路径
-I(大写i)指定头文件所在路径
-l(小写L)

指定库名称(去掉前后缀)

如下,假如我要使用这个静态库,我先将这个压缩包解压:

 接下来我们进行g++编译,这里编译时我们手动指定所需要的库名(-l)、库路径(-L)、头文件路径(-I)。

对于静态库的使用,还有第二种方法如下:

第二种方式使用静态库:将头文件以及库文件安装在系统目录

由于gcc/g++在编译时,会默认去系统目录搜索,进行路径匹配,这也是为什么我们平常用c/c++标准库时,编译时不需要再指定库路径和头文件路径。

库所在系统路径:/lib64

头文件所在系统路径:/usr/include

 这里需要注意的是,一般我们不要轻易修改系统的环境,因此我们用完后要手动删除,否则会一直存在。

动态库的打包

上面讲了静态库的打包和使用,接下来将动态库的打包和使用,以及动态库链接的原理。

动态库的打包分为以下几个步骤:

  1. 将存放方法的源文件进行编译,编译后(含预处理--编译--汇编)生成以.o为后缀的可重定位二进制目标文件。同时在编译时生成与位置无关码。(gcc/g++ -c -fPIC)
  2. 直接gcc/g++对所有的.o文件进行编译,同时加上-shared选项,打包成动态库即可。(gcc/g++ -shared)
  3. 将动态库与头文件压缩后发送给他人即可供他人使用

以上静态库例子打包成动态库,步骤如下所示:

 紧接着我们可以将动态库与头文件进行压缩,将压缩包给other用户,供他人使用。

 这里有一点需要注意,就是我们一般会把头文件,单独放在一个目录,库文件单独放在一个目录。(上面静态库的例子忘记了,这里说一下。)

动态库的使用

接下来我们已other的身份,进行使用动态库,我们先将压缩包进行解压,然后进行编译,编译时指定头文件、库文件的路径,以及库名。

 虽然可以正常编译,但是此时我们运行可执行程序,就会出现如下报错:

这是因为我们在编译时,仅仅只是告诉了编译器,但是OS并不知晓,OS只会在系统路径,以及当前所在路径下进行查找头/库文件。因此此时会报错。(静态链接并不会,因为生成的可执行程序的运行,不会依赖库),这时常用的解决方法有如下几种:

 1、将库文件拷贝到系统路径

此时我们假如将我们的第三方动态库,拷贝到系统路径/lib64下,即可正常运行。如下:

 需要注意的是,我们一般不会对系统环境进行更改,用完后要进行删除,否则的话,下一次重新登陆,系统路径下还是会存在我们自己的第三方库。

2、将库路径导入环境变量LD_LIBRARY_PATH中

用export指令,将库路径(绝对路径)导入环境变量LD_LIBRARY_PATH中,如下:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/qidunyan/linux-exercise/test_23_06/test_23_0607/otherPeople/mylib/

此时程序依然可以正常运行

 该方法的好处就是用完后,我们不需要对该环境变量进行删除库的路径,因为下次重新登陆时,该环境变量会被更新。

3、对系统配置文件/etc/ld.so.conf.d进行更改

系统配置文件/etc/ld.so.conf.d中存放的都是以.conf为后缀的文件,该文件内存放的是路径。我们只需要将动态库的绝对路径,放在一个以.conf为后缀的文件中,再将该文件拷贝到系统配置文件内即可。如下:

 但是此时运行的话,依然会显示失败,因为我们没有对配置文件进行更新,我们只需要输入指令:ldconfig,进行更新配置文件即可。

 当然,我们为了不污染系统环境,使用完后也要记得手动删除,否则会一直存在。

动静态库链接的原理

为什么静态链接生成的可执行程序,不会依赖库文件呢?因为在编译阶段会将库中方法的代码加载到可执行程序中,这样就会出现一个情况,假如同一个方法比如printf,被调用了多次,这也就会导致printf实现的代码,被重复复制了多次,出现大量冗余重复的代码,这也就是为什么静态链接生成的可执行程序体积大小非常大的原因。

而动态链接则不是这样,程序在链接动态库时,会通过库的起始地址+偏移量,来找到函数方法所在的位置,而这个偏移量,就是我们生成的与位置无关码。其实就是0 1 2 3 4...这样的偏移量,也就是说,只要知道库的起始地址,就能根据0 1 2 3...这样的偏移量,来找到各自的方法。为什么叫与位置无关码呢?因为库被映射到地址空间的地址是不确定的,但是偏移量是固定的,这样不管库被映射到哪个地址,通过偏移量都可以找到函数所在的位置。(举个例子,假如我对你说,我距离你10米远,那么不管你的位置在哪里,只需要从你的位置+10米,就可以找到我,这个10米,就类似位置无关码)

而在程序运行时,动态库会被加载到物理内存,同时会通过页表映射到进程对应的地址空间中的共享区。此时动态库的地址也就有了。且同一个方法,它的库地址+偏移量相同,所以代码只需要存在一份即可,避免了代码冗余。同时假如存在多个进程同时运行且使用同一个库,那么动态库也只需要在内存中加载一份,然后映射到各自的共享区,通过库地址+偏移量就可以跳转到方法的实现。大大节省了空间的使用。

补充

云服务器默认只存在动态库,因此我们若想使用C/C++静态库,需手动安装

安装C/C++静态库

sudo yum install -y glibc-static
sudo yum install -y libstdc++-static

另外,我们需要知道以下几点:

gcc/g++默认采用动态链接,但是假如只存在静态库,则gcc/g++只会进行静态链接,同样,只存在动态库,也只能进行动态链接(即使我们加上 -static)。

而若动静态库同时存在,则gcc/g++会默认进行动态链接。也可以手动指定进行静态链接(-static)


end.

生活原本沉闷,但跑起来就会有风!🌹

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

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

相关文章

TypeScript学习(1)- ts基础配置介绍

目录 TypeScript是什么&#xff1f; TypeScript开发环境搭建 TypeScript是什么&#xff1f; 以JavaScript为基础构建的语言一个JavaScript的超集typescript扩展了JavaScript&#xff0c;并添加了类型可以在任何支持JavaScript的平台中执行TS不能被js解析器直接执行&#xff0…

【多线程与高并发】- 锁的机制与底层优化原理

锁的机制与底层优化原理 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 一个有梦有戏的人 怒放吧德德 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#…

c语言第二课------地基打牢,基础打紧,不可放弃

作者前言: 欢迎小可爱们前来借鉴我的gtieehttps://gitee.com/qin-laoda 目录 变量的作用域和生命周期 常量 字符串转义字符注释 选择语句 循环语句 函数 _________________________________________________ 这次我们接着上一篇博客,我们接着来继续C语言的学习 变量的作用…

四十六、B+树

这一次我们来介绍B树。 一个m阶的B树具有如下几个特征&#xff1a; 1.根结点至少有两个子女。 2.每个中间节点都包含k-1个元素和k个孩子&#xff0c;其中 m/2 < k < m 3.每一个叶子节点都包含k-1个元素&#xff0c;其中 m/2 < k < m 4.所有的叶子结点都位于同一层。…

Python学习ing

Python中 字符串不能通过 &#xff0c;把 数字等非字符串&#xff0c;进行拼接&#xff0c; 但Javascript中是可以的。 会把数字自动转换成字符串&#xff0c; 但python 提供了占位符 %s % 占位符 city "徐州" age 20 message "我是%s人,今天%s岁" …

面向对象继承

2. 面向对象特征二&#xff1a;继承(Inheritance) 2.1 继承的概述 说到继承我们会想到什么 在Java面向对象程序设计中的继承&#xff0c;多个类中存在相同属性和行为时&#xff0c;将这些相同的内容抽取到单独一个类&#xff08;父类&#xff09;中&#xff0c;然后所有的类继…

新能源汽车保养vr仿真教学软件为职业培训带来新的思路和方法

电动车电池更换VR虚拟体验是一种利用VR虚拟现实技术实现对电动车电池更换进行模拟仿真演示和实操训练的虚拟仿真实验教学课件&#xff0c;相比传统教学模式&#xff0c;有效提高学生的实践能力和技能水平。 通过VR技术模拟现场&#xff0c;使培训人员可以身临其境滴观摩操作过程…

(二)Liunx下ElasticSearch快速搭建

1.下载安装 1).环境准备&#xff1a; 操作系统&#xff1a;centos7 es版本&#xff1a;8.8.1 jdk:17 es与jdk等兼容支持查看 2).下载安装包上传到服务器&#xff0c;官网地址 https://www.elastic.co/cn/downloads/elasticsearch 3).解压文件 tar -zxvf elasticsearch-8.8.…

信息差永远存在,聪明的人也永远能利用信息差赚钱

信息的差异永远存在&#xff01; 例子一&#xff1a; 在2018年&#xff0c;某宝在央视春晚中成功地获得了广告名额&#xff0c;但与此同时&#xff0c;上百位工程师没想到的是&#xff0c;这是一个恶梦的开始&#xff01; 由于春晚当晚的访问人数过多&#xff0c;服务器立刻发…

模块化相关知识点

这里写目录标题 模块化概述基本使用&#xff08;包的跨模块使用&#xff09;介绍代码演示 模块服务的使用&#xff08;跨模块接口的实现&#xff09;简介具体代码 模块化 概述 基本使用&#xff08;包的跨模块使用&#xff09; 介绍 代码演示 首先 要在第一个模块里&#xf…

路径规划算法:基于算术优化优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于算术优化优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于算术优化优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

SpringCloud公共模块项目搭建(二)

我们新建module公共模块项目 microservice-common&#xff0c;主要是放一些其他项目公用的东西&#xff0c;比如实体类&#xff0c;工具类等等&#xff1b; 新建module 勾选 create a simple project 取下module 名称 mircoservice-common 这里用默认的jar pom.xml 加下 jpa…

SpringBatch从入门到实战(四):表结构

batch_job_instance -> batch_job_execution/batch_job_execution_params -> batch_job_execution_context 一&#xff1a;batch_job_instance 作业实例 同一个作业&#xff0c;同一套作业参数 唯一标识一条记录&#xff0c;首次启动时插入一条数据。 字段描述JOB_IN…

MySQL 数据库基础

这里写目录标题 一、Mysql的基本概念数据库管理系统&#xff08;DBMS&#xff09;数据库系统 二、数据库的发展史三、 主流的数据库介绍数据库分为关系型数据库与非关系型数据库关系型数据库非关系型数据库介绍 四、 操作Mysql常用的数据类型&#xff1a;常看数据库结构查看当前…

共探数字化时代安全新思路,腾讯安全联合FreeBuf举办安全运营高峰论坛

近日&#xff0c;由网络安全行业门户FreeBuf主办&#xff0c;腾讯安全协办的「安全运营高峰论坛深圳站」在深圳益田威斯汀酒店圆满举行。在这场网络安全行业盛会上&#xff0c;数百名来自全国各地的网安人共聚一堂&#xff0c;围绕“安全运营”、“新时代下威胁情报对企业的价值…

为什么推荐使用线程池?

为什么推荐使用线程池&#xff1f; 更多优秀文章&#xff0c;请扫码关注个人微信公众号或搜索“程序猿小杨”添加。 背景&#xff1a; 若并发的线程数量很多&#xff0c;且每个线程都是执行一个时间很短的任务就结束了&#xff0c;这样频繁创建线程就会大大降低系统的效率&…

如何使用Leangoo领歌scrum工具自动生成燃尽图

在上一篇&#xff0c;我为大家介绍了如何使用Leangoo领歌敏捷工具管理Sprint Backlog_哆啦B梦_的博客-CSDN博客&#xff0c;今天我们一起来看看Leangoo领歌敏捷工具是如何自动生成Scrum燃尽图的。 什么是scrum燃尽图&#xff1f; 燃尽图是在项目完成之前&#xff0c;对需要完…

什么是大数据?

现在大数据发展的如火如荼&#xff0c;也有不少小伙伴对于什么是大数据比较感兴趣&#xff0c;那么大数据在比较官方的定义是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合&#xff0c;是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力…

文字表达的力量:如何通过编辑和校对优化内容

有效的文字表达能够为读者传递清晰的信息&#xff0c;产生深远的影响。通过编辑和校对优化内容&#xff0c;你可以提升文字表达的力量。以下是一些建议&#xff0c;帮助你在编辑和校对过程中优化内容&#xff0c;提高文字表达的力量。 1.确保内容的逻辑性和连贯性 一个具有说服…

15款好用的效果图设计制作软件推荐

无论你是设计师、工程师、室内设计师还是3D艺术家&#xff0c;你都必须熟悉效果图设计制作软件。 在这篇文章中&#xff0c;我们将向您介绍15个值得尝试的效果图设计制作软件&#xff01; 1.即时设计 即时设计是一款「专业UI设计工具」&#xff0c;不受平台限制&#xff0c;…