【Linux】软硬连接 | 静动态库

🪐🪐🪐欢迎来到程序员餐厅💫💫💫

          主厨:邪王真眼

主厨的主页:Chef‘s blog  

所属专栏:青果大战linux

总有光环在陨落,总有新星在闪烁


你说得对,但是这就是期末临近,一遍学操作系统,一边琢磨怎么复习自己的专业课,还有六级!!!!!  

软链接

 使用下面的指令即可生成软链接文件

基本语法:ln -s [目标文件或目录路径] [软链接文件名]

概念 

可以看到我们生成了一个软链接文件,文件后缀可以随便写,因为linux解析大多数文件中不会考虑文件后缀,但是为了方便我们自己认识还是规范写比较好。

上图红框的第一个字母是l,表示这是一个软链接文件

软链接生成的是一个独立文件,因为他有自己独立的inode

软链接的文件内容是所指向的目标文件的路径,可以理解为windows中的快捷方式,你可以通过该软链接文件打开目标文件。

如上图,我们在一个文件中输入字符串,之后可以通过该文件的软链接文件访问它。 

请注意输入目标文件的路径时建议用用绝对路径,因为软链不会解析那个相对路径,举个例子,

[qingguo@host project23_link]$ sudo ln -s ./t1 /usr/bin/t3

 我通过相对路径在usr/bin目录下建立t1的软链接,那么软链接链接的路径就不是此时的./即/home/qingguo/project23_link/,而是链接过去之后的./即usr/bin。

可以看到链接后的文件表示找不到目标文件

 让后我把目标文件移动到了 软链接文件的目录即./usr/bin下,此时就表示可以使用了。


用途

  •  1.对文件

就像我们在window中使用快捷键一样,要使用一个文件但是他藏在很深的目录里,找起来太麻烦了,于是你可以写个软链接把该软连接文件统一放到一个地方,使用就方便了(比如桌面)。

  •  2.对目录 

同样的加入有个目录下的东西你经常需要看,但是目录很长,输入起来很麻烦,你可以可以对该目录进行软链接,这样就不用输入那一长串目录,只用输入软链接的文件名了.

[qingguo@host ~]$ ln -s /usr/bin ub
[qingguo@host ~]$ sudo ll ub

  • 3.伪装指令

通过这种方式你也可以把自己的可执行程序放到usr/bin目录下,就可以当指令用了

删除软链接文件 

 要删除软链接文件可以直接rm,也可以使用unlink+软链接文件(带路径)


硬链接

基本语法:ln  [目标文件或目录路径] [硬链接文件名]

概念

可以看出生成方式上,软硬链接只差了一个-s

可以看出生成的硬链接文件的inode和原文件一样 ,并且硬链接后红框圈住的数字加了1

我们不认为硬链接文件是个独立的文件,毕竟他没有独立的inode,他本质就是所处目录下新增的一组已存在的文件名与inode的映射关系。

而那个红框圈的数字就是硬链接数,表示有多少文件名指向该文件的inode,所以要删除一个文件不是删一个文件就够了,而是要把和该文件有映射的所有文件都删掉,这里采用的就是引用计数

 我们删掉了原文件,此时软链接失效,但是我们依据可以依靠硬链接访问该文件的内容,这就是引用计数删除的体现。

可以发现,一个独立的文件没有对他使用硬链接时硬链接数为1,但是文件夹的硬连接数却是2

因为目录有一个隐藏文件".",该文件也是指向该文件夹的,所以硬链接数为2

接着我在该dir1里有新建了一个文价夹,dir1的硬连接数加1了。

 

因为新建的文件夹里有隐藏文件"..",它指向上级目录即dir1,

这些"."和".."采用的就是硬链接。

 这里我们就可以解释为什么根目录再去cd  ..   就不能继续前进了,因为他的".." 指向的文件就是自己本身,和"."是一样的。看下图根目录下的“.”和“..”的inode都是2。

用途

  • 1.备份文件

显然我们直前学的备份就是cp指令,这个指令的备份是新建了一个文件,这显然增加了空间开销,现在我们就可以使用硬链接进行备份,空间开销约等于0,优雅、真是太优雅了。

链接目录 

硬链接不可以链接目录,原因是硬链接目录会形成环状路径,

这样的路径,请问A-hard.link的上级目录算是C还是根目录,他的下一级目录是B还是E和F,这就没法解析目录了啊,所以OS禁止用户硬链接目录,这时候就有人问了:

我们不是刚讲了“.”和“..”这两个隐藏文件就是硬链接,而且是对目录的硬链接,这不矛盾了吗

没错,OS就是这样,在这个硬链接文件目录上,只许州官放火不许百姓点灯,因为他自己其实还加了一些特殊处理,我们知道这个事就行。


软链接则不然,我们可以tree一下

显然,OS对软链接的文件不会直接展开他链接的文件,而是就先把他当作一个普通文件看待 ,这样就可以链接目录啦。


静态库

ldd指令可以查看一个文件链接的库

  

准备工作

首先我们先完成源码,自己写俩头文件以及函数实现,等下把他们封装成库来使用

  • mystdio.c 
#include"mystdio.h"
#include<unistd.h>
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>
mFILE* mfopen(const char*filename,const char*mode){int fd=-1;if(*mode=='r'){fd= open(filename,O_RDONLY);
}else if(*mode=='w'){fd= open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
}
else if(*mode=='a'){fd=open(filename,O_WRONLY|O_CREAT|O_APPEND,0666);
}
mFILE*f=(mFILE*)malloc(sizeof (mFILE));
if(!f){close(fd);return NULL;
}
f->fd=fd;
f->flag=FLUSH_FULL;
f->cap=1024;
f->size=0;
return f;
}
int  mfwrite(char*str,int num,mFILE*stream){memcpy(stream->buffer+stream->size,str,num);stream->size+=num;int flag=1;if(stream->flag==FLUSH_LINE){if(stream->size>0&&stream->buffer[stream->size-1]=='\n'){flag=write(stream->fd,stream->buffer,stream->size);stream->size=0;} }else if(stream->flag==FLUSH_FULL){if(stream->size>stream->cap*9/10){flag=write(stream->fd,stream->buffer,stream->size);printf("%d",stream->size); stream->size=0;}}return flag;
}
void mfflush(mFILE*stream){write(stream->fd,stream->buffer,SIZE);
}
int mfclose(mFILE*stream){mfflush(stream);return  close(stream->fd);
}
  • mystdio.h
#pragma once
#define SIZE 1024
#define FLUSH_NODE 0
#define FLUSH_LINE 1
#define FLUSH_FULL 2
struct mFILE{int fd;int flag;//文件刷新方式char buffer[SIZE];int cap;
int size;
};
typedef struct mFILE mFILE;
mFILE* mfopen(const char*filename,const char*mode);
int  mfwrite(char*str,int num,mFILE*stream);
void mfflush(mFILE*stream);
int mfclose(mFILE*stream);
  •  mystring.h
#include"mystring.h"
int mstrlen(const char*arr){int i=0;while(arr[i])i++;return i;
}
  • mystring.c
#pragma once
int mstrlen(const char*arr);
  • main.c 
#include<mystdio.h>
#include<stdio.h>
#include<mystring.h>
int main(){printf("%d",mstrlen("aaa"));mFILE*p=mfopen("t1.txt","w");mfclose(p);
}


 介绍

 【基本语法】

ar -rc libname.a [要打包的.o文件]
  1. ar事archive的缩写,意思是把。。归档
  2. -r表示repalce,即若库中已有同名文件则进行替代
  3. -c表示creat,若库中没有该文件则创建

什么是静态库

 静态库(Static Library),在计算机编程领域,是一种将多个目标文件(通常是编译后的代码)打包在一起的文件格式。它的扩展名在不同的操作系统和编译器下可能有所不同,例如在 Unix/Linux 系统中常为.a(archive 的缩写),在 Windows 系统中常为.lib。静态库就像是一个代码仓库,里面包含了一系列可以被其他程序调用的函数和变量的编译后版本

在理解这些后,我们可以写一个makefile,它可以创建一个库,把库和头文件放到目标路径,以及清理所有数据  

%.o:%.cgcc -c $<//.o文件的实现方法写哪里都可以,如果在执行某条命令时发现依赖文件没有生成,系统会自动检查makefile中的所有指令看有没有用于生成该依赖文件的
libmystdio.a:mystdio.o mystring.oar -rc $@ $^
.PHONY:clean
clean:rm -rf *.a *.o stdc
.PHONY:output
output:mkdir -p stdc/include//注意要先写mkdir,再写cp指令,这里是按照顺序执行的mkdir -p stdc/libcp -rf *.c stdc/includecp -rf *.a stdc/libtar -czf stdc.tgz stdc//顺带打个包压缩一下,可以直接发给需要的同学(太优雅了)

使用方法

  • 1.头文件和库都在标准路径下

把头文件放到usr/bin目录下,库文件放到/lib64

直接gcc编译链接

gcc -o main main.c

好了,不出意外就会报错,我来给你分析一下

对于头文件如果是以<>的方式包含,那么系统会自动去标准路径及usr/bin目录下挨个找该头文件是否存在,

对于库,OS会在默认标准路径即/lib64下查找,但是你要告诉他要找的库名字! 

-l +库名字表示去找该库

注意库的名字是去掉.a或.so的后缀,去掉lib前缀

gcc -o main main.c -l mystdio

也可以这么写 

gcc -o main main.c -lmystdio

这时候就有人问了,为什么我们平常用gcc编译链接标准库就不用-l+库名字

老弟,你猜猜他为什么叫gcc?

在编译 C 程序时,GCC(GNU Compiler Collection)对于 C 标准库有隐式链接的机制。C 标准库是非常基础且常用的库,几乎每个 C 程序都会用到其中的一些函数,如stdio.h中的printfscanf等。为了方便开发者,GCC 编译器默认会自动链接 C 标准库

g++也是同理 


  • 2.库不放到标准路径下

-L +路径表示除了系统路径,也要去这个路径下找库

gcc -o main main.c -lmystdio -L ./my
  • 库和头文件.h都不在标准路径下

-I +路径表示除了系统路径,也要去这个路径下找头文件

gcc -o main main.c -lmystdio -L ./my -I ./include


动态库

生成动态库

gcc -o 动态库名称 [依赖的.o文件] -shared

生成需要的.o文件

gcc -fPIC  -o .o文件名称 -c 源文件名称

显然我们这次多了一个-fPIC(Position - Independent Code)选项,翻译一下就是位置无关代码,他的作用是使得生成的.o文件代码是位置无关的,这是因为动态库在内存中的加载位置是不确定的,需要代码能够在任何位置正确执行。关于这个问题我们下节课会细讲。

 libmystdio.so:mystdio.o mystring.o                                                                                                                                                                                              gcc -o $@ $^ -shared%.o:%.cgcc -fPIC -o $@ -c $<.PHONY:cleanclean:rm -rf *.o *.so

有了动态库我们就可以gcc编译链接了,方法和静态库是一样的,还是

  • 1.头文件和库都在标准路径下

  • 2.库不放到标准路径下

  • 3.库和头文件.h都不在标准路径下

在生成了可执行文件后直接./main执行会报错,ldd查看 会发现我们main找不到库的路径    

  

但是我们gcc的时候不是给他指定路径了吗。

因为gcc是用来生成可执行文件的,我们给的路径也是生成可执行文件的时候才会被看到,现在已经到了执行可执行文件的时候了,操作系统会默认到lib/64链接需要的库,显然我们的库不在这里,那么我们就要再告诉OS这个库的路径了。  

  • 解决方法1.

把我们的动态库拷贝到lib64目录,可以cp,也可以软链接(记得用绝对路径)  

  • 解决方法2.

修改环境变量

系统会到LD_LIBRARY_PATH这个环境变量存储的路径下找库,我们把我们自己的库的路径加进来就好了

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/qingguo/project23_link/other/stdc/lib/

环境变量在退出shell后就重置了,为了保存效果我们可以去该用户的根目录下,先cd ~到用户的根目录,再找到.bashrc,

 

修改里面的LD_LIBRARY_PATH即可

此时就可以找到库的路径了 

就可以运行了。 


  •   解决方法3

修改配置文件

在/etc路径下,有一个ld.so.conf.d的文件夹

我们在这里touch一个后缀为.conf的文件,在里面写入我们的库的路径(不带最后的库名称)即可

要用root,貌似sudo提权 也不好使,建议直接su

通过以上方法,我们就成功让库=文件找到了对应的库的路径 

链接规则 

现在我们的可执行文件包含四个库,三个是标准库ABC,一个是我们自己实现的库D,并且ABC库既有动态库也有静态库。

  1. 当D库动静态库都有的时候,默认gcc链接优先使用动态库链接ABCD
  2. 当D有静态库并且想使用静态库就加-static选项,此时链接ABCD都会用静态库

  3. D只有动态库但是加了-static选项则会报错

  4. D只有静态库即使没有指定-static,此时ABC会链接动态库,但是D会使用静态库 

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

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

相关文章

消防物证管理系统|DW-S404实现消防物证智能化管理

一、系统概述 智慧消防物证管理系统DW-S404系统旨在借助现代信息技术&#xff0c;达成消防物证管理的高效化、安全化及智能化管理目标。该系统运用物联网、大数据、云计算等先进技术&#xff0c;实现对消防物证从产生到销毁的全生命周期跟踪与监控&#xff0c;从而增强物证管理…

Java的封装、继承、多态

书接上文&#xff0c;我们聊完了Java的类和对象&#xff0c;有没有唤起你脑海的一些记忆呢&#xff0c;我们有了类和对象的基础之后&#xff0c;我们就可以衍生出来封装继承和多态。 封装 我理解一个东西&#xff0c;我一般会先想这个是什么&#xff0c;再是怎么用&#xff0…

【大数据技术基础 | 实验十四】Kafka实验:订阅推送示例

文章目录 一、实验目的二、实验要求三、实验原理&#xff08;一&#xff09;Kafka简介&#xff08;二&#xff09;Kafka使用场景 四、实验环境五、实验内容和步骤&#xff08;一&#xff09;配置各服务器之间的免密登录&#xff08;二&#xff09;安装ZooKeeper集群&#xff08…

操作系统Lesson7 - 线程编程模型和进程间通信概述

文章目录 进程和线程的区别线程非安全函数时序问题进程间通信竞态条件 进程和线程的区别 一句话&#xff1a;进程资源独立&#xff0c;线程资源共享。 当系统内核不支持线程时&#xff0c;我们只能用用户空间来描述线程&#xff1b;而如果内核支持线程&#xff0c;我们可以在创…

距离与AoA辅助的三维测距算法,适用于自适应基站数量的情况。订阅专栏后可直接查看完整源代码

本MATLAB 代码实现了一个基于距离与到达角(AoA)的三维测距系统,主要用于在动态环境中估计目标物体的位置。提供本算法与仅侧角(AoA)的定位误差对比 文章目录 代码运行结果源代码代码功能概述主要步骤分析初始化部分AOA定位绘图部分输出部分代码的应用和意义总结代码运行结…

dd破坏asm磁盘头恢复---惜分飞

有朋友对asm disk的磁盘头dd了2048byte的数据 通过分析,gi软件版本,确认是11.2.0.4 Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production With the Real Application Clusters and Automatic Storage Management options. ORACLE_HOME /u01/app/…

网络测速工具

1. SPEEDTEST https://www.speedtest.net/ 2. 测速网 测速网 - 专业测网速, 网速测试, 宽带提速, 游戏测速, 直播测速, 5G测速, 物联网监测,Wi-Fi 7,Wi-Fi 6,FTTR,全屋Wi-Fi - SpeedTest.cn 3. 字节比特换算 bps&#xff08;bits per second&#xff09; 字节和比特的换算…

PDF处理的创新工具:福昕低代码平台尝鲜

在当今数字化时代&#xff0c;PDF文件的处理和管理变得越来越重要。福昕低代码平台是新发布的一款创新的工具&#xff0c;旨在简化PDF处理和管理的流程。通过这个平台&#xff0c;用户可以通过简单的拖拽界面上的按钮&#xff0c;轻松完成对Cloud API的调用工作流&#xff0c;而…

R语言 | ComplexHeatmap 画注释若干基因的热图 //todo

一般顺序&#xff1a; 先用 pheatmap 聚类再用 ComplexHeatmap 做可视化&#xff1a;添加顶部、左侧聚类颜色&#xff0c;显示若干代表性基因 genec("Gene18", "Gene19", "Gene7","Gene3", "Gene9", "Gene15") …

模型案例:| 手机识别模型!

导读 2023年以ChatGPT为代表的大语言模型横空出世&#xff0c;它的出现标志着自然语言处理领域取得了重大突破。它在文本生成、对话系统和语言理解等方面展现出了强大的能力&#xff0c;为人工智能技术的发展开辟了新的可能性。同时&#xff0c;人工智能技术正在进入各种应用领…

解谜类游戏《迷失岛2》等如何抽象出一套通用高效开发框架?

解谜类游戏以精妙的谜题设计和引人入胜的故事叙述为特点&#xff0c;考验着玩家的智慧与观察力。《迷失岛2》与《南瓜先生2九龙城寨》正是这一领域的佳作。游戏以独特的艺术风格和玩法设计吸引了大量玩家&#xff0c;而它们背后隐藏着一套强大的框架。 上海胖布丁游戏的技术总…

【C++探索学习】第十九弹——进程替换:深入解析操作系统中的进程替换机制

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 在Linux操作系统中&#xff0c;进程替换&#xff08;Process Replacement&#xff09;是一个重要的概念&#xff0c;它允许程序通过系统调…

SSH克隆github项目

1、生成密钥 ssh-keygen -t rsa -C "你的邮箱xxx.com" 全程回车即可&#xff08;不用输入ras文件名及密码&#xff09;、为了方便下面的公钥查看 2、配置公钥 查看公钥内容 cat c:\Users\xxx\.ssh\id_rsa.pub(修改为自己的路径及名字) 将公钥内容复制并粘贴至…

ASP.NET Core 9.0 静态资产传递优化 (MapStaticAssets )

一、结论 &#x1f4a2;先看结论吧&#xff0c; MapStaticAssets 在大多数情况下可以替换 UseStaticFiles&#xff0c;它已针对为应用在生成和发布时了解的资产提供服务进行了优化。 如果应用服务来自其他位置&#xff08;如磁盘或嵌入资源&#xff09;的资产&#xff0c;则应…

电子信息工程自动化 单片机自动门控制系统设计

摘 要 伴随着社会经济的发展进步、科学技术的发展进步以及人民群众日常生活质量的逐渐提升&#xff0c;自动门开始全面进入人民群众的生活&#xff0c;逐渐发展成为了宾馆、大型超市、政府等当代建筑里必须配备的设备&#xff0c;是建筑自动智能化综合水平的主要标准之一。它具…

防火墙有什么作用

防火墙的作用&#xff1a;1. 提供网络安全防护&#xff1b;2. 实施访问控制和流量过滤&#xff1b;3. 检测和阻止恶意攻击&#xff1b;4. 保护内部网络免受未经授权的访问&#xff1b;5. 监控网络流量和安全事件&#xff1b;6. 支持虚拟专用网络&#xff08;VPN&#xff09;。防…

Cesium-地球材质-坡度

1. 创建viewer 创建viewer并添加地形 const viewer new Cesium.Viewer("cesiumContainer", {terrainProvider: await Cesium.CesiumTerrainProvider.fromIonAssetId(3956, {requestVertexNormals: true}) }); 2. 创建canvas色条 添加getColorRamp方法&#xff0…

企业网双核心交换机实现冗余和负载均衡(MSTP+VRRP)

MSTP&#xff08;多生成树协议&#xff09; 通过创建多个VLAN实例&#xff0c;将原有的STP、RSTP升级&#xff0c;避免单一VLAN阻塞后导致带宽的浪费&#xff0c;通过将VLAN数据与实例绑定&#xff0c;有效提升网络速率。 VRRP&#xff08;虚拟路由冗余协议&#xff09; 用…

VTK编程指南<三>:基于VTK入门程序解析来理解VTK基础知识

1、VTK入门程序 下面是一个完整的Vtk入门程序&#xff0c;我们基于这个程序来对VTK的基本知识进行一个初步了解。 #include <iostream>#include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2 VTK_MODULE_INI…

React基础知识四 Hooks

什么是hooks&#xff1f; (coderwhy) hooks是react 16.8&#xff08;2019年&#xff09;出的新特性。 react有两种形式来创建组件——类式和函数式。在hooks之前类式组件就是react最主流的编程方式。 这个时候&#xff0c;函数式组件是非常鸡肋的&#xff0c;几乎没什么用。因…