当前位置: 首页 > news >正文

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

目录

  • 文件系统与动静态库的基本了解
    • 文件系统
      • 了解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++优先链接动态

相关文章:

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

目录文件系统与动静态库的基本了解文件系统了解Access Modify Changeinode硬链接软链接静态库与动态库概念静态库的制作使用静态库动态库的制作使用动态库总结如何制作文件系统与动静态库的基本了解 文件系统 了解Access Modify Change 当文件没有被打开时&#xff0c;他们存…...

netty——IO、NIO、AIO进化之路

IO、NIO、AIO进化之路BIO——同步阻塞IO伪异步阻塞IONIO——同步非阻塞IOAIO——异步IO总结本文会说明各种IO的特点、分别解决了什么样的问题做一个分析阐述&#xff0c;并结合Java代码例子来辅助理解&#xff0c;像这些的历史演进和详细的底层原理网上很多&#xff0c;所以我们…...

AI稳定生成图工业链路打造

前沿这篇文章会以比较轻松的方式&#xff0c;跟大家交流下如何控制文本生成图片的质量。要知道如何控制文本生成质量&#xff0c;那么我们首先需要知道我们有哪些可以控制的参数和模块。要知道我们有哪些控制的参数和模块&#xff0c;我们就得知道我们文本生成图片的这架机器或…...

20230220华南金牌主板u盘启动

20230220华南金牌主板u盘启动 2023/2/20 10:29 百度搜索&#xff1a;华南金牌主板u盘启动 https://www.zhihu.com/question/498121895?utm_id0 华南金牌主板b85u盘启动怎么设置? 华南金牌主板b85u盘启动怎么设置 海的那边 上小学后才发现还是幼儿园好混…… 华南一般是F7和F1…...

测试团队都在用哪些不错的测试用例管理平台?盘点6大主流测试管理系统

测试团队使用的主流测试用例管理平台&#xff1a;1.PingCode &#xff1b;2.TestRail&#xff1b;3.Testlink&#xff1b;4.ZephyrJira&#xff1b;5.TestCenter&#xff1b;6.飞蛾。目前市面上的测试用例管理工具有很多&#xff0c;但由于针对的项目、领域、目标用户&#xff…...

linux 系统编程之线程

线程 文章目录线程1 线程概念2 NPT安装线程 man page&#xff1a;查看指定线程的 LWP 号&#xff1a;3 线程的特点4 线程共享资源5 线程非共享资源6 线程的优缺点7线程常用操作1 线程号pthread_self函数&#xff1a;pthread_equal函数:参考代码2 错误返回值分析参考代码3 线程的…...

从0开始学python -35

Python3 File(文件) 方法 open() 方法 Python open() 方法用于打开一个文件&#xff0c;并返回文件对象。 在对文件进行处理过程都需要使用到这个函数&#xff0c;如果该文件无法被打开&#xff0c;会抛出 OSError。 注意&#xff1a;使用 open() 方法一定要保证关闭文件对…...

1.14 golang中的结构体

1. 结构体 Go语言中没有“类”的概念&#xff0c;也不支持“类”的继承等面向对象的概念。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。 1.1. 类型别名和自定义类型 1.1.1. 自定义类型 在Go语言中有一些基本的数据类型&#xff0c;如string、整…...

原创不易,坚持更难

早上CSDN发消息&#xff0c;今天是创作满三年的纪念日&#xff0c;邀请写一篇博文&#xff0c;谈谈感受 开博原因 2020年是一个特殊的年份&#xff0c;疫情刚爆发第一年&#xff0c;也是第一次居家办公&#xff0c;从过完年就一直居家办公&#xff0c;一直居家了38天。2020年…...

计算机网络 | 谈谈TCP的流量控制与拥塞控制

文章目录一、TCP的流量控制1、利用滑动窗口实现流量控制【⭐⭐⭐】2、如何破解【死锁】局面❓二、TCP的拥塞控制1、拥塞控制的一般原理① 解决网络拥塞的误区② 拥塞控制与流量控制的关系【重点理解✔】2、TCP的拥塞控制方法① 接收窗口【rwnd】与拥塞窗口【cwnd】② 慢开始和拥…...

Flask入门(7):内置装饰器(钩子函数)

目录7.内置装饰器&#xff08;钩子函数&#xff09;7.1 before_request7.2 after_request7.3 before_first_request7.4 error_handlers7.5 template_filter7.6 template_global复习装饰器基础及其应用&#xff0c;可参考文章&#xff1a;闭包和装饰器 7.内置装饰器&#xff08…...

Java8新特性

✨作者&#xff1a;猫十二懿 ❤️‍&#x1f525;账号&#xff1a;CSDN 、掘金 、个人博客 、Github &#x1f389;公众号&#xff1a;猫十二懿 写在最前面 在企业中更多的都是使用 Java8 &#xff0c;随着 Java8 的普及度越来越高&#xff0c;很多人都提到面试中关于Java 8 也…...

哈希表题目:设计哈希集合

文章目录题目标题和出处难度题目描述要求示例数据范围解法一思路和算法代码复杂度分析解法二思路和算法代码复杂度分析题目 标题和出处 标题&#xff1a;设计哈希集合 出处&#xff1a;705. 设计哈希集合 难度 3 级 题目描述 要求 不使用任何内建的哈希表库设计一个哈希…...

java static关键字 万字详解

目录 一、为什么需要static关键字&#xff1a; 二、static关键字概述 : 1.作用 : 2.使用 : 三、static修饰成员变量详解 : 1.特点 : 2.细节 : ①什么时候考虑使用static关键字? ②静态变量和非静态变量的区别&#xff1f; ③关于静态变量的初始化问题 : ④关于静态变…...

光谱实验反射、透射光谱测量

标题反射、透射光谱测量的基本原理  暗背景/基线&#xff1a;Dark………………………………………………………………0%  &#xff08;空&#xff09;白参考&#xff1a;Reference…………………………………………………………100%  样品反射/透射光谱&#xff1a;Sampl…...

【基础算法】之 冒泡排序优化

冒泡排序思想基本思想: 冒泡排序&#xff0c;类似于水中冒泡&#xff0c;较大的数沉下去&#xff0c;较小的数慢慢冒起来&#xff08;假设从小到大&#xff09;&#xff0c;即为较大的数慢慢往后排&#xff0c;较小的数慢慢往前排。直观表达&#xff0c;每一趟遍历&#xff0c;…...

Python | 线程锁 | 3分钟掌握【同步锁】(Threading.Lock)

文章目录概念无锁加锁死锁解决死锁概念 threading.Lock 同步锁&#xff0c;可以用于保证多个线程对共享数据的独占访问。 当一个线程获取了锁之后&#xff0c;其他线程在此期间将不能再次获取该锁&#xff0c;直到该线程释放锁。这样就可以保证共享数据的独占访问&#xff0c…...

Linux下安装MySQL8.0的详细步骤(解压tar.xz安装包方式安装)

Linux下安装MySQL8.0的详细步骤 第一步&#xff1a;下载安装配置 第二步&#xff1a;修改密码&#xff0c;并设置远程连接&#xff08;为了可以在别的机器下面连接该mysql&#xff09; 第三步&#xff1a;使用Navicat客户端连接 搞了一台云服务器&#xff0c;首先要干的活就是…...

leaflet 绘制多个点的envelope矩形(082)

第082个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中如何根据多边形的几个坐标点来绘制envelope矩形。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共78行)安装插件相关API参考:专栏目标示例…...

CAJ论文怎么批量免费转换成Word

大家都知道CAJ文件吗&#xff1f;这是中国学术期刊数据库中的文件&#xff0c;这种文件类型比较特殊。如果想要提取其中的内容使用&#xff0c;该如何操作呢&#xff1f;大家可以试试下面这种免费的caj转word的方法,多个文档也可以一起批量转换。准备材料&#xff1a;CAJ文档、…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...