文件系统与动静态库的基本了解

news/2024/4/20 22:47:26/文章来源:https://blog.csdn.net/weixin_52319694/article/details/129129498

目录

  • 文件系统与动静态库的基本了解
    • 文件系统
      • 了解Access Modify Change
      • inode
      • 硬链接
      • 软链接
    • 静态库与动态库
      • 概念
      • 静态库的制作
      • 使用静态库
      • 动态库的制作
      • 使用动态库
      • 总结如何制作

文件系统与动静态库的基本了解

文件系统

了解Access Modify Change

当文件没有被打开时,他们存放在哪里呢?是磁盘上面,我们可以通过命令行上面输入ls -l(读取存储在磁盘上的文件信息,然后显示出来) 或者 stat filename来查看文件信息,ls命令已经很熟悉了,我们这里来看看stat命令
这里我们来着重了解一下这三个时间:

  • Access:最近一次访问时间
  • Modify:最近一次修改时间–>指文件内容
  • Change:最后一修改时间–>指文件属性

我们经常使用的Makefile和make,我们知道当我们不做修改时,如果已经make过一次之后,再次make就会报错说文件已经存在(虚拟依赖除外),那么操作系统到底为什么能够知道文件已经编译过不需要在编译了呢?原因就在于Modify也就是修改时间,如果一个文件刚刚编译形成了一个可执行程序,那么形成的可执行程序它的修改时间一定比文件的修改时间要晚,这样Makefile就可以根据两个文件的最近一次的修改时间来判断是否需要继续编译,以下是例子:

  • 要注意虽然说Access是最近一次的访问时间,可是linux内核版本在2.6左右往上,这个访问时间都不会被立即刷新,要有一定的时间间隔,OS才会自动进行更新时间,主要是因为访问这一操作比较频繁,如果频繁的刷新会让系统变卡
  • 当我们修改文件内容的是时候,大概率是会修改文件的属性的,比如:可能会更改文件的大小(文件大小也是属性)

inode

Linux上:文件名在系统层面没有意义,文件名是给我们用户用的,Linux中真正标识一个文件,是通过文件的inode编号来标识的,当我们的文件没有被加载到内存中的时候,它们就存储在磁盘上面,磁盘中最小的存储单元是扇区(1扇区=512Bytes),文件系统的最小存储单元是block(1Block=4kb=8扇区)


我们都知道磁盘上面有很多的扇形分区,如果我们把扇形的分区抽象成长方形来看待我们就会得到这样一个图:

  • Linux ext2文件系统,上图为磁盘文件系统图(内核内存映像肯定有所不同),磁盘是典型的块设备,硬盘分区被划分为一个个的block。一个block的大小是由格式化的时候确定的,并且不可以更改。例如mke2fs的-b选项可以设定block大小为1024、2048或4096字节。而上图中启动块(Boot Block)的大小是确定的

  • Block Group:ext2文件系统会根据分区的大小划分数个Block Group都有这相同的结构组成

  • 超级块(Super Block):存放文件系统本身的结构信息。记录信息主要有:block和inode的总量,未使用的block和inode的数量,一个Block和一个inode的大小,最近一次的挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Supper Block的信息被破坏就相当于整个文件系统结构就被破坏了

  • GDT(Group Descriptor Table),组描述符表。由很多组描述符组成,整个分区分成多少个组就对应有多少个组描述符。每个组描述符(Group Descriptor)存储一个组的描述信息,例如在这个组中从哪里开始是inode表,从哪里开始是数据块,空闲的inode和数据块还有多少个等等。

  • 块位图(Block Bitmap):这里面记录着Data Block中哪个数据块被占用,哪个数据块没被占用

  • inode位图(inode Bitmap):每个bit表示一个inode空间是否空闲可用

  • inode节点表(inode Table):存放文件属性如文件大小,所有者,最近修改时间等等

  • 数据区(Data blocks):存放文件内容


将属性和文件数据分开存放实际上应该如何实现呢?

我们以touch一个文件为例来看:
创建文件主要有以下四个操作:

  1. 存储属性

    内核先找到空闲的inode节点(这里是1049849),内核把文件信息记录到其中

  2. 存储数据

    该文件需要三个磁盘块,内核找到了三个空闲块400,600,800.将内核缓冲区的第一块数据复制到400接着是600依次类推

  3. 记录分配情况

    文件内容按顺序400,600,800存放,内核在inode上的磁盘分布记录了上述块列表

  4. 添加文件名到目录

    新的文件名file.txt。Linux如何在当前文件目录中记录这个文件内核将入口(149849,file.txt)添加到目录文件,文件名和inode之间的对应关系将文件名和文件内容及其属性连接起来


几个相关问题:(仅是我的理解)

目录的本质是什么呢?

  • 本质可以理解为存放了文件名和对应的inode的链接关系的文件,可以通过文件名去找到对应的inode,从而可以通过inode table来查看文件的属性或者内容数据

删除的本质是什么呢?

  • 删除的本质其实就是把inode bitmap中的对应位置改为未被占用即可,这也是有时候误删之后可以恢复的原理,当如果误删掉一个文件之后如果自己不会恢复就尽量保持原样,不要再进行多余的操作,去找专业的人去解决,因为保持刚删除后的样子能最大程度保证删除之后的数据块没有被覆盖,这样恢复的可能会更大(也就是把inode和数据块之间重新建立链接)

硬链接

首先怎么使用硬链接,在shell中的做法是:ln 被链接的文件路径及文件名 文件名 我们看到,真正找到磁盘上文件的并不是文件名,而是inode。 其实在Linux中可以让多个文件名对应于同一个inode,硬链接本质就不是一个独立的文件,而是一个文件名和inode编号的映射关系,因为它没有自己的inode

  • file1.txt和hard.txt的链接状态完全相同,它们被称为指向文件的硬连接。内核记录了这个连接数inode是1053256硬连接数是2
  • 我们在删除文件时干了两件事:
    1. 在目录中将对应的记录删除
    2. 将硬连接数-1,如果为0,则将对应的磁盘释放
  • 目录文件在创建时就有两个硬连接

软链接

用法与硬连接相同只是多了个-s:ln -s 要链接文件的路径以及文件名 文件名

  • 软链接形成的是一个新的文件,因为它具有自己的inode属性,也有自己的数据块(保存的是指向文件的所在路径和文件名)
  • 如果被链接的文件被删除,那么链接文件也会失效

静态库与动态库

概念

在Linux中如果是动态库,库文件是以.so为后缀的;静态库是以.a为后缀的;在windows中动态库.dll,静态库.lib

  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间
  • ldd filename:显示可执行程序依赖的库,这里就是libc.so.6库名字就是c库
  • 库文件的命名:libXXXX.so or libXXXX.a-…
  • 动静态库的名字是去掉lib前缀和.so-或者.a-后缀剩下的部分
  • 一般云服务器可能没有内置语言的静态库,而只有动态库可以自己添加一下sudo yum install glibc -static


同样file命令也可以查看可执行程序是什么链接,这里就是动态链接,使用的是共享库


静态库的制作

首先我们我们先了解一下原理,我们都知道一个文件想要到可执行,需要以下几个步骤:预处理,编译,汇编,链接。其中汇编之后会形成一个.o下标的二进制文件,并不可以被直接执行,叫可重定向目标文件(-c 是开始进行程序的编译,完成汇编工作就停下),这个.o文件就是制作动静态库所需的文件,因为其本身已经具有可执行的属性了,只是没有被链接,动静态库其实也就是打包这些.o文件并且附代上.h的头文件,了解到这里我们开始进行一个简单的静态库的制作

  • 制作静态库我们可以使用ar -rc打包静态库,ar是gnu归档工具,rc表示replace and create

  • 查看已经制作完成的静态库:ar -tv查看打包内容

    t:列出静态库中的文件
    v:verbose 详细信息

举例:

  1. 首先我们先创建四个文件,文件内容如下:

    //add.h,add.c,sub.h,sub.c
    //sub.h
    #include<stdio.h>
    extern int sub(int x,int y);
    //sub.c
    #include"sub.h"
    int sub(int x,int y)
    {return x-y;
    }
    //add.h
    #include<stdio.h>
    extern int add(int x, int y);
    //add.c
    #include "add.h"
    int add(int x,int y)
    {return x + y;
    }
    
  2. 创建出Makefile文件

    • 我们之前写的那些代码也都用了库(如c库),为什么没有指名这些选项呢?—>之前的库,在系统的默认路径下:/lib64/usr/lib, /usr/include等等
    • 所以如果我们不想带这些选项,我们可以直接把对应的库和头文件拷贝到默认路径下首先是可行的,但是非常不推荐这样做,这会污染库,有时如果库的一些文件与拷贝文件重名还会覆盖掉原先的库
    • 一般软件安装的过程其实也就是上面的过程

这样就把静态库制作完成并打包了

使用静态库

我们制作好了静态库应该如何使用呢?其实也就是链接的过程,我们需要先写一段简单的代码:

//因为头文件不在同一目录下,所以需要指定一下路径
#include "./libs/add.h"
#include "./libs/sub.h"
int main()
{int x=20;int y=10;printf("add = %d\n",add(x,y));printf("sub = %d\n",sub(x,y));return 0;
}

在这里插入图片描述
这样就可以去执行了,因为静态链接的特性,编译的时候会把静态库代码拷贝进我们所写的测试代码中去,所以只要指定好路径,编译形成可执行文件之后就可以直接运行了

动态库的制作

动态库的制作原理和静态库基本一致,总的来说就是打包.o文件具体我们来看操作,还是上面的例子:

  1. 创建四个文件并写上相应的内容

    //sub.h sub.c add.h add.c
    
  2. 创建出Makefile文件

    • gcc -fPIC -c $<产生.o目标文件,程序内部的地址解决方案是:与位位置无关,库文件可以在内存的任何位置加载,而且不影响和其他程序的关联性(-fPIC的作用)
    • -shared就是形成一个动态链接的共享库

之后直接make,make libd即可形成动态库

使用动态库

在使用之前我们得先认识到一个东西:文件编译形成可执行文件的是编译器,而形成的可执行文件要运行,需要的是加载器,两者不是同一个东西

使用动态库同样需要写一个简单的代码

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

然后开始写Makefile,内容与静态库的使用基本一致
静态库这样就直接可以运行了,但是动态库不行,这只是代表了编译能通过,但是运行时会报错
这种情况的解决方法有很多种但是这里推荐一种使用LD_LIBRARY_PATH具体用法如下:

  • export LD_LIBRARY_PATH = 库所在的绝对路径
  • 为什么这里不需要指定库名(这里是dynamic)呢?从ldd可以看出可执行文件已经知道所链接的库名了,只是没有路径找不到
  • 这种方法需要每一次打开端口的时候都设置一次,export只适用于当前登录,退出之后所做的修改就清除了

还有其他的方法就是:

  1. 拷贝.so文件到系统共享库路径下,一般指/usr/lib不过不推荐
  2. ldconfig 配置/etc/ld.so.conf.d/,ldconfig更新

总结如何制作

  1. 所有的源代码,都需要先被编译成为.o(可重定向目标文件)
  2. 制作动静态库的本质就是将所有的.o打包(使用ar或者gcc来进行打包)
  3. 交付头文件 + -.a 或者 -.so 文件

gcc和g++优先链接动态

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

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

相关文章

数据挖掘,计算机网络、操作系统刷题笔记50

数据挖掘&#xff0c;计算机网络、操作系统刷题笔记50 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;orac…

(考研湖科大教书匠计算机网络)第五章传输层-第八节1:TCP连接管理理论部分(三次握手与四次挥手)

获取pdf&#xff1a;密码7281专栏目录首页&#xff1a;【专栏必读】考研湖科大教书匠计算机网络笔记导航此部分内容借鉴博主【小林coding】 &#xff0c;其对计算机网络内容的图解可以说是深入浅出&#xff0c;尤其是三次握手和四次挥手这一部分&#xff0c;堪称全网最佳。所这…

webpack5打包工具的使用

目录 -----------------------------基础篇------------------------------- 一、为什么需要打包工具 二、基本使用 1、模式 2、使用步骤 三、基本配置 1、五大核心概念 2、准备 Webpack 配置文件 3、运行指令 四、开发模式 五、处理样式资源 1、处理CSS资源 2、处…

100份简历才找一个合适的,2023,软件测试岗位饱和了吗?

各大互联网公司的接连裁员&#xff0c;政策限制的行业接连消失&#xff0c;让今年的求职雪上加霜&#xff0c;想躺平却没有资本&#xff0c;还有人说软件测试岗位饱和了&#xff0c;对此很多求职者深信不疑&#xff0c;因为投出去的简历回复的越来越少了。 另一面企业招人真的…

闪光桐人の实习日记(2023年2月20-27日)

前往闪闪の小窝以获得更好的阅读和评论体验 文章目录2023年2月20日&#xff08;Vue入门&#xff09;概念Vue基础Vue中的MVVMVue的体验Vue的生命周期Vue指令Vue组件VueRouter前后端路由的区别工作原理两种模式比较route跟router的区别路由属性导航守卫Vuex概述5种基本对象基本使…

Qt线程QThread详解

目录前言1.QThread介绍2.QThread示例一3.QThread示例二4.线程同步前言 在程序中使用线程可以提高程序的性能、并发性、响应性和稳定性&#xff0c;使得程序设计更加灵活和简单。但是&#xff0c;线程编程也有一些挑战&#xff0c;如线程安全性和死锁等问题需要格外注意。我们使…

【1】linux命令每日分享——mkdir

大家好&#xff0c;这里是sdust-vrlab&#xff0c;Linux是一种免费使用和自由传播的类UNIX操作系统&#xff0c;Linux的基本思想有两点&#xff1a;一切都是文件&#xff1b;每个文件都有确定的用途&#xff1b;linux涉及到IT行业的方方面面&#xff0c;在我们日常的学习中&…

【机器学习】决策树-ID3算法

1.ID3算法 ID3算法利用信息增益进行特征的选择进行树的构建。信息熵的取值范围为0~1&#xff0c;值越大&#xff0c;越不纯&#xff0c;相反值越小&#xff0c;代表集合纯度越高。信息增益反映的是给定条件后不确定性减少的程度。每一次对决策树进行分叉选取属性的时候&#x…

网络计划--时间参数的计算和优化

根据网络图的基本概念和原则绘制出网络图之后&#xff0c;我们可以计算网络图中有关的时间参数&#xff0c;主要目的是找出关键路线&#xff0c;为网络计划的优化、调整和执行提供明确的时间概念。如下图中从始点①到终点⑧共有4条路线&#xff0c;可以分别计算出每条路线所需的…

使用maven搭建父子工程项目

创建父子工程&#xff0c;可以通过父工程来引入jar&#xff0c;定义统一的版本号等。更方便对整个项目的jar包实现统一化管理&#xff0c;让项目的层次更加清晰。一、创建父工程第一步&#xff1a;file–>new–>project–>maven默认使用jdk1.8&#xff0c;不引入任何j…

音视频基础之视频主要概念

视频主要概念 **视频码率&#xff1a;**kb/s&#xff0c;是指视频文件在单位时间内使用的数据流量&#xff0c;也叫码流率。码率越大&#xff0c;说明单位时间内取样率越大&#xff0c;数据流精度就越高。 **视频帧率&#xff1a;**fps&#xff0c;通常说一个视频的25帧&…

ur3+robotiq ft sensor+robotiq 2f 140配置rviz仿真环境

ur3robotiq ft sensorrobotiq 2f 140配置rviz仿真环境 搭建环境&#xff1a; ubuntu: 20.04 ros: Nonetic sensor: robotiq_ft300 gripper: robotiq_2f_140_gripper UR: UR3 在安装sensor和gripper之前&#xff0c;先简单配置一下UR机械臂的仿真环境&#xff0c;可参考这篇博…

jenkins下载与简单使用

1.jenkins下载 因为我仍然使用的是jdk1.8进行开发&#xff0c;所以我下载的是jenkins2.332.1版本&#xff08;jenkins2.346.1版本在2022年末不再支持java8&#xff0c;如果项目使用的是jdk11可以继续使用该jenkins版本&#xff09;&#xff0c;更多版本下载请点击jenkins下载 …

ADRC自抗扰控制总结

目录 前言 1.ADRC形式 1.1形一 1.2形二 2.被控对象 3.仿真分析 3.1仿真模型 3.2仿真结果 4.学习问题 前言 前面的3篇文章依次介绍了微分跟踪器TD、状态观测器ESO和非线性状态误差反馈NLSEF三部分内容&#xff0c;至此ADRC的结构已经介绍完毕&#xff0c;现在对分块学习…

pytorch零基础实现语义分割项目(四)——模型训练与预测

模型训练与预测项目列表前言损失函数one_hotDice LossFocal Loss模型参数与训练预测项目列表 语义分割项目&#xff08;一&#xff09;——数据概况及预处理 语义分割项目&#xff08;二&#xff09;——标签转换与数据加载 语义分割项目&#xff08;三&#xff09;——语义…

JVM系统优化实践(1):JVM概览

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e;这是多年之前做过的学习笔记&#xff0c;今天再翻出来&#xff0c;觉得仍然是记忆犹新。「独乐乐不如众乐乐」&#xff0c;就拿出来分享给「众乐乐」吧。目前大多…

用户画像——如何构建用户画像系统

为什么需要用户画像 如果你是用户,当你使用抖音、今日头条的时候,如果平台推荐给你的内容都是你感兴趣的,能够为你节省大量搜索内容的时间。 如果你是商家,当你投放广告的时候,如果平台推送的用户都是你的潜在买家,能够使你花更少的钱,带来更大的收益。 这两者背后都…

KeePass敏感信息明文传输漏洞复现 (CVE-2023-24055)

一、漏洞描述 漏洞简述 KeePass 是一款免费的开源密码管理器&#xff0c;可帮助您以安全的方式管理您的密码。您可以将所有密码存储在一个数据库中&#xff0c;该数据库由一把万能钥匙锁定。因此&#xff0c;您只需记住一个主密钥即可解锁整个数据库。数据库文件使用目前已知…

面试个3年自动化测试,测试水平一言难尽。。。。

公司前段缺人&#xff0c;也面了不少测试&#xff0c;结果竟然没有一个合适的。 一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在10-20k&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。 看简历很多都是3年工作经验&#xff0c;但…

中间件安全—Apache常见漏洞

中间件安全—Apache常见漏洞1.Apache常见漏洞1.1.Apache介绍1.2.Apache HTTPD 换行解析漏洞&#xff08;CVE-2017-15715&#xff09;1.2.1.漏洞介绍1.2.2.漏洞环境1.2.2.1.运行漏洞环境1.2.2.2.访问漏洞环境1.2.3.漏洞复现1.2.3.1.拦截1.2.3.2.添加换行1.2.3.3.访问文件1.3.Apa…