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

news2024/9/20 9:07:18

目录

  • 文件系统与动静态库的基本了解
    • 文件系统
      • 了解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.coloradmin.cn/o/358894.html

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

相关文章

广州蓝景—结合chatGPT下的教育模式变化

最近爆火的人工智能AI聊天工具ChatGPT&#xff0c;不仅在互联网&#xff0c;更是在各行各业中&#xff0c;得到了广泛的传播&#xff0c;应该没有哪一个不知道它的存在&#xff0c;但其实你又是否知道&#xff0c;其实ChatGPT是一类模型的统称&#xff0c;随着人工智能的快速发…

【vue】elemente-ui table toggleRowSelection 默认选择无效[已解决]

项目场景&#xff1a; 点击按钮&#xff0c;弹出一个弹出框&#xff0c;内部出现一个table表&#xff0c;表内数据是动态获取&#xff0c;同时得勾选上几个table表的数据&#xff0c;类似以下的图 问题描述 点击按钮显示弹出框&#xff0c;加载table中的数据&#xff0c;默…

《自动驾驶规划入门》专栏结语

一、 源起 2021年10月12日&#xff0c;化学工业出版社的金编辑根据博客中留下的微信号联系上我&#xff0c;问我有没有出书的想法。从小到大&#xff0c;书与文字在我心里是有着神圣地位的。我在“想试试”与“害怕做不好”这两种矛盾的心情中&#xff0c;还是先应了下来。签了…

计算机SCI期刊自引率一般是多少? - 易智编译EaseEditing

论文常用来指进行各个学术领域的研究和描述学术研究成果的文章&#xff0c;是探讨问题进行学术研究的一种手段&#xff0c;又是描述学术研究成果进行学术交流的一种工具&#xff0c;包括学年论文、毕业论文、学位论文、科技论文、成果论文等。 一般来说&#xff0c;论文的自引…

ros中时间的概念:ros::Time、ros::Duration、定时器ros::Timerros::Rate

1. ros时间格式说明 有时刻和持续时长(可以是负数)&#xff0c;分为秒和纳秒&#xff0c;换算关系&#xff1a;1sec1e9nsec。Time指的是某个时刻&#xff0c;而Duration指的是某个时段。 int32 sec int32 nsec 2. ros::Time::now() 记录当前时刻 3. ros::Duration 代表持续的…

RedisTemplate最常用方法

前言&#xff1a;RedisTemplate常用方法介绍&#xff0c;根据RedisTemplate封装了Redis的一些常用的原生操作RedisUtil工具类。 一、SpringDataRedis简介 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-d…

MinIo-SDK

3.2.5 SDK 3.2.5.1上传文件 MinIO提供多个语言版本SDK的支持&#xff0c;下边找到java版本的文档&#xff1a; 地址&#xff1a;https://docs.min.io/docs/java-client-quickstart-guide.html 最低需求Java 1.8或更高版本: maven依赖如下&#xff1a; XML<dependency&g…

2023爱分析· 云管理服务(MSP)市场厂商评估报告:华创方舟

目录 1. 研究范围定义 2. 云管理服务&#xff08;MSP&#xff09;市场定义 3. 厂商评估&#xff1a;华创方舟 4. 入选证书 1. 研究范围定义 数字化时代&#xff0c;应用成为企业开展各项业务的落脚点。随着业务的快速发展&#xff0c;应用的功能迭代变得越来越…

深度学习常用的优化器整理

常见优化器整理 一、SGD&#xff08;随机梯度下降&#xff09; 公式&#xff1a; 经典的mini-batch SGD使用的很多&#xff0c;效果也比较不错&#xff0c;但是存在一部分问题 选择恰当的初始学习率很困难学习率调整策略受限于预先制定的调整规则相同的学习率被应用于各个参数…

经理与员工工资关系-课后程序(JAVA基础案例教程-黑马程序员编著-第四章-课后作业)

【案例4-6】经理与员工工资案例&#xff08;利用多态实现&#xff09; 欢迎点赞关注收藏 【案例介绍】 案例描述 某公司的人员分为员工和经理两种&#xff0c;但经理也属于员工中的一种&#xff0c;公司的人员都有自己的姓名和地址&#xff0c;员工和经理都有自己的工号、工…

中国高速公路行业市场规模及未来发展趋势

中国高速公路行业市场规模及未来发展趋势编辑中国高速公路行业市场规模正在迅速增长。随着中国经济的快速发展和城市化的加速&#xff0c;对交通基础设施的需求也在不断增加。高速公路是最有效的交通工具&#xff0c;可以大大缩短交通时间&#xff0c;提高出行效率。因此&#…

志趣相投的人总会相遇——社科院与杜兰大学金融管理硕士项目

志同道合的人&#xff0c;才会喜欢同一片风景&#xff0c;志趣相投的人&#xff0c;总有一天会相遇。社科院与杜兰大学金融管理硕士项目为什么能吸引一大批“上班族”呢&#xff0c;我们一起去了解一下。社科院与杜兰大学中外合作办学硕士项目无需参加全国联考&#xff0c;通过…

springMvc源码解析

入口&#xff1a;找到springboot的自动配置&#xff0c;将DispatcherServlet和DispatcherServletRegistrationBean注入spring容器&#xff08;DispatcherServletRegistrationBean间接实现了ServletContextInitializer接口&#xff0c;最终ServletContextInitializer的onStartup…

Seata-Server分布式事务原理加源码(一) - 微服务之分布式事务原理

概念 基础概念&#xff1a;事务ACID • A&#xff08;Atomic&#xff09;&#xff1a;原子性&#xff0c;构成事务的所有操作&#xff0c;要么都执行完成&#xff0c;要么全部不执行&#xff0c;不可能出现部分成功部分失 败的情况。 • C&#xff08;Consistency&#xff09;…

【测试开发】Dubbo接口测试技术,测试开发进阶必备(附源码)

Dubbo 是什么&#xff1f; Dubbo 是阿里巴巴开源的一套 RPC 方案&#xff0c;因为理念很契合微服务&#xff0c;这几年很火&#xff0c;用户里面不凡京东&#xff0c;当当&#xff0c;去哪儿等大公司。 RPC 场景 Dubbo 架构 官网也提供了一个很简单实用的 Demo 来演示 Dubbo …

企业级信息系统开发学习笔记1.4 初探Spring——采用Java配置类管理Bean

文章目录零、本讲学习目标一、课程引入二、采用Java配置类管理Bean&#xff08;一&#xff09;打开项目&#xff08;二&#xff09;创建子包&#xff08;三&#xff09;创建杀龙任务类&#xff08;四&#xff09;创建勇敢骑士类&#xff08;五&#xff09;创建Spring配置类&…

电商数据查询平台:母婴行业妈妈用品全网热销,头部品牌格局初现

以往&#xff0c;奶粉、纸尿裤这类产品基本就代表了整体母婴市场中的消费品。而如今&#xff0c;随着母婴行业的高速发展和消费升级&#xff0c;母婴商品的种类日益丰富&#xff0c;需求也不断深入。 在京东平台&#xff0c;母婴大品类中除了包含婴童相关的食品&#xff08;奶粉…

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

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

飞塔Fortinet防火墙SSL VPN双因素身份认证(2FA)方案

作为行业领先的防火墙厂商&#xff0c;飞塔Fortinet结合了高性能 VPN 功能&#xff0c;代表了网络安全的新概念。其中飞塔Fortinet防火墙 SSL VPN 因其突出的安全性能而被广泛应用在远程办公场景中。但在 SSL VPN 登录时用户仅需输入用户名和固定的静态密码&#xff0c;若遭遇账…

AWS S3常用功能总结回顾

本文用于记录与分享工作中遇到的s3的基础使用方法 工具介绍 本文采用s3Browser对s3进行可视化管理 基本元素 端点Endpoint桶Bucket账号AccessKey密码SecreteKey 说明 本文基于JavaSDK进行演示代码&#xff0c;下文的代码都只包含核心部分&#xff0c;异常捕捉、流关闭、…