Linux篇:文件系统

一、共识原理:
文件=文件内容+文件属性
磁盘上存储文件=存文件的内容(数据块)+存文件的属性(inode)
Linux的文件在磁盘中存储是将属性和内容分开存储的。

二、硬件简述:
1. 认识硬件
磁盘:唯一的一个机械设备,也是一个外设。磁头一面一个,磁头和盘面不接触。是永久性存储介质,高温会退磁。
内存:掉电易失性存储介质。
磁带:类似于磁盘。

2、磁盘的存储构成
磁盘被访问的最基本单元是扇区(512字节/4KB),我们可以把磁盘看作有无数个扇区构成的存储介质。
要把数据存到磁盘,第一个解决的问题是定位一个扇区,哪一面定位用哪个磁头,哪一个磁道,哪一个扇区。
磁头左右摆动,其实质是定位磁道和柱面的过程(运动越少,效率越高;运动越多,效率越低)。
在软件设计上,设计者一定要有意识的将相关数据放在一起。
磁带延展开,逻辑上是线性的,所以磁盘在逻辑上也是线性的。基于扇区的数组,任意一个扇区都有下标。

3、回归到硬件:不仅仅有CPU有寄存器,其他设备外设也有,磁盘也有。
控制寄存器(rw):控制IO方向。
数据寄存器:存储数据。
地址寄存器:逻辑地址(LBA)。
状态寄存器:表示结果。

三、对硬件进行抽象理解(文件系统ext2):

1、分治: 分区->块组->文件系统。

Data blocks:存文件内容的区域,以块的形式呈现,常见的文件系统块大小是4KB(一般而言,每个块只有自己的数据)。

inode Table:很多inode。
inode:inode结构体,包含单个文件的所有属性(inode number,文件类型,权限,引用计数,拥有者,所属组,ACM时间,int blocks[NUM]等),大小是128字节(一般而言,一个文件,一个inode)(文件文件名不在inode保存)。
注:
①在linux中文件的属性中,不包含文件的名称,只知道文件的编号。查找一个文件仅需找到它的inode编号,从而在它的inode表中找到inode,从而找到其blocks数组,根据数组中记载的块号按顺序读出文件内容。
②block数组规定:分为直接索引和简介间接索引。
直接索引:存储文件内容。
间接索引:不存储文件内容,而是继续存储我们的文件版号,从而创建更大的文件。

Block bitmap比特位的位置和块号映射起来,比特位的内容表示该块是否被使用。 
inode bitmap:比特位的位置和inode的编号映射起来,比特位的内容表示inode是否有效。
问:上一个文件的时候用不用把块(文件内容)清空呢?
答:不用。根据文件inode编号,找到inode bitmap(发现位图有效),转而去找inode table,读取其属性获得对应的inode和数据块地址关系,读取所有块号,在bitmap和block map里所有的块号全部清零,其次,根据inode编号找到其bitmap由1置为0。

Group Descriptor Table(不会在每个组都存在):描述整个分组基本的使用情况:一共有多少个组,每个组的大小,每个组的inode数量,每个组的block数量,每个组的起始inode,文件系统的类型与名称等。

Super Block:文件系统的信息:里面包含的是整个分区的基本使用情况。

格式化:每一个分区在被使用前,都必须提前先将部分文件系统的属性信息提前设置进对应的分区中,方便我们后续使用这个分区或者分组。

2、文件理解:
①新建一个文件,系统要做什么?
通过新建路径确定分区,在该分区内分配inode——查询Group Descriptor Table是否还有未使用的inode,然后扫描inode bitmap位图结构并读取,选择最近的未使用的编号,将该比特位由0置1。未来可通过inode编号确定分区。在inode Table内找到inode,将文件属性填入。在Block bitmap确认写入数据量的大小,遍历未使用的块,将对应的块号填充到inode属性中特定的下标里,然后直接跳转到对应的块中,把内容填充进去。
②删除一个文件,系统要做什么?
根据文件所处目录,确定文件所处分区,根据inode范围确定分组,用自己inode编号减去起始inode编号,进而可以在inode bitmap进行索引,根据inode编号在位图中对应的比特位由1置0,根据inode将Block Bitmap对应比特位由1置0。(删除=允许被覆盖)。
③查找一个文件,系统要做什么?同理。
④修改一个文件,系统要做什么?同理。

3、如何理解目录
①Linux系统中,一个文件,一个inode,每一个inode都有自己的inode编号(inode的设置,是以分区为单位的,不能跨分区)
inode表示文件的所有属性,但是文件名并不属于inode内的属性!
②问:可是我怎么知道一个文件的inode编号?使用者从来没关心过inode,用的是文件名。
答:通过目录查找。
③目录也是文件,也有自己的inode,也有自己的内容和属性。目录数据块中存储文件的文件名和对应文件inode的映射关系。
④同一个目录下不能有同名文件,因为key值不能相同。文件名冲突系统就无法找到指定文件了。
⑤目录下,没有w,我们无法创建文件。即便创建了文件,文件名与inode的映射关系也无法写到目录文件的数据块里。
⑥目录下,没有r,我们无法查看文件。无法读取目录所对应数据块的文件名与inode的映射关系无法得到。
⑦目录下,没有x,我们就无法进入这个目录。cd目录名本质上是找到目录的inode,但没有x,无法进入目录,无法更新当前目录环境变量。
⑧问:可是目录是文件,也有inode的编号。怎么找?
答:查任何一个目录使,都要从当前目录开始向上递归找到根目录(此文件文件名确定/),找到该数据块,里面的所有文件子目录数据都可以找到。(绝对路径)
⑨Linux系统中,会把用户最常访问的若干目录路径信息通过dentry缓存。

四、软硬链接:

软链接是一个独立的文件,具有独立的inode
硬链接不是一个独立的文件,因为它没有独立的inode。

1、如何理解硬链接?
所谓建立硬链接,本质其实就是在特定目录的数据块中新增文件名和指向的文件的inode编号的映射关系(类似于取别名)。
任意一个文件,无论是目录,还是普通文件,都有inode。
每一个inode内部,都有一个叫做引用计数的计数器(有多少个文件名指向该文件)(默认引用计数为1,自己指向自己)。
目录里保存的是文件名:inode编号的映射关系(默认引用计数为2,有自己目录的文件名和inode映射关系)(目录内部的.文件是该目录的一个硬链接)。

2、如何理解软链接?
软链接是一个独立的文件,有独立的inode,也有独立的数据块,他的数据块里面保存的是指向文件的路径(类似于快捷方式)。

3、为什么要用软链接?
任意路径软件在系统中能找到的/usr/bin目录下建立软连接,就能不带路径执行。

4、为什么要用硬链接?
通常用来进行路径定位,采用硬链接,可以进行目录间切换。硬链接能够维持Linux整体的目录结构。
注:Linux不允许用户对目录建立硬链接,因为会引发环路问题。(而系统可以,比如.和..)。

五、内存管理简述

1、内存的本质是对数据的临时存取,所以我们在系统层面上把内存看作一个大型的缓冲区。内存中的大部分数据未来都会加载到磁盘里或者释放。物理内存以页框为单位和磁盘以页帧为单位进行数据交互(4KB)。

2、问:为什么要以4KB的方式进行拷贝?
答:
①减少IO的次数/减少访问外设的次数---硬件。
②基于局部性原理的预加载机制---软件。

3、操作系统如何管理内存?
操作系统提供了虚拟地址空间的概念,用户在应用层只能看见虚拟地址,但操作系统也能看到内存的物理地址。操作系统管理内存时,先描述,再组织——用struct page结构体描述page必要的属性信息,存储到struct page mem_array数组中(其中数组的下标称为页号),对内存的管理变成了对数组的管理!
用户要访问一个内存时,只需要先直接找到这个4KB对应的page,就能在系统中找到对应的物理页框。所有申请内存的动作都是在访问内存page数组。
申请内存的本质是检测数组中结构体里flag标志位是否被使用,若未使用则将page的比特位置1即可。

4、伙伴系统算法,slab分派器(了解即可)。

5、文件页缓冲:Linux中我们的每个进程打开的每一个文件都要有自己的inode属性和自己的文件页缓冲区。数据通过基数树/基树(字典树)写入到文件页缓冲区。文件的内容是有偏移量的!可以通过文件内容偏移量按照比特位构成字典序,在字典树中找到相应的文件偏移量与内存中配置对应的映射关系。从而让文件有序地进行刷新。

6、IO子系统:操作系统层面上会提供一个公共的队列IO request queue,所有的上层进程最终将数据通过文件写到内存中,文件中的配置构建成struct request结构体封装到队列里。操作系统所谓的刷新就是将队列里的数据依次提交给磁盘。同时也可以通过IO排序,IO合并优化该过程。

六、动静态库 

1. 回顾:站在库的制作者角度。
libXXX.a---静态链接
libYYY.so---动态链接
把我们提供的方法给别人用,可以把源文件直接给他,也可以把我们的源文代码想办法打包成库(库+.h)
静态库原理:将.c文件编译成.o文件,将.o文件打包成.a文件,将main.c文件编译为.o文件,两者一结合为最后的可执行程序。

//mymath.h#pragma once#include <stdio.h>extern int myerrno;int add(int x, int y);
int sub(int x, int y);
int mul(int x, int y);
int div(int x, int y);
//mymath.c
#include "mymath.h"int myerrno = 0;int add(int x, int y)
{return x + y;
}int sub(int x, int y)
{return x - y;
}int mul(int x, int y)
{return x* y;
}int div(int x, int y)
{if(y == 0){myerrno = 1;return -1;}return x / y;
}
//Makefilelib=libmymath.a$(lib):mymath.oar -rc $@ $^  //$@ $^表示这些文件的起始和尾
mymath.o:mymath.cgcc -c $^  //$^:形成同名的.o文件.PHONY:clean
clean:rm -rf *.o *.a lib.PHONY:output
output:mkdir -p lib/includemkdir -p lib/mymathlibcp *.h lib/includecp *.a lib/mymathlib
[root@hecs-210801 lesson27]# ll
total 12
-rw-r--r-- 1 root root 228 Nov 26 10:19 Makefile
-rw-r--r-- 1 root root 251 Nov 26 10:10 mymath.c
-rw-r--r-- 1 root root 148 Nov 26 10:09 mymath.h
[root@hecs-210801 lesson27]# make
gcc -c mymath.c
ar -rc libmymath.a mymath.o
[root@hecs-210801 lesson27]# make output
mkdir -p lib/include
mkdir -p lib/mymathlib
cp *.h lib/include
cp *.a lib/mymathlib
[root@hecs-210801 lesson27]# ll
total 24
drwxr-xr-x 4 root root 4096 Nov 26 10:27 lib
-rw-r--r-- 1 root root 1880 Nov 26 10:27 libmymath.a
-rw-r--r-- 1 root root  228 Nov 26 10:19 Makefile
-rw-r--r-- 1 root root  251 Nov 26 10:10 mymath.c
-rw-r--r-- 1 root root  148 Nov 26 10:09 mymath.h
-rw-r--r-- 1 root root 1704 Nov 26 10:27 mymath.o
[root@hecs-210801 lesson27]# tree lib
lib
├── include
│?? └── mymath.h
└── mymathlib└── libmymath.a2 directories, 2 files

删除lib的指令:

[root@hecs-210801 lesson27]# rm -rf lib

未来我们要把库给别人时仅需提供lib文件夹即可。

在其他目录下使用该库时所包头文件为:

#include “lib/include/mymath.h”

或者让系统在指定目录下找头文件,库文件:

[root@hecs-210801 lesson27]# gcc main.c -I ./lib/include/ -L ./lib/mymathlib/ -lmymath

2、站在库的使用者角度:
①第三方库往后使用的时候,必定要用gcc -l。
②深刻理解errno的本质。
③gcc链接程序时,默认是动态链接的。如果系统中只提供静态链接,gcc则只能对该库进行静态链接。
④如果系统中需要链接多个库,则gcc可以链接多个库。

3、解决下载不到静态库的方法:
①拷贝到系统默认的库路径/lib64/usr/lib64/(库的安装)。
②在系统默认的库路径/lib64/usr/lib64/建立软链接。

4、解决下载不到动态库的方法:
①拷贝到系统默认的库路径/lib64/usr/lib64/(库的安装)。
②在系统默认的库路径/lib64/usr/lib64/建立软链接。
③将自己的库所在的路径,添加到系统的环境变量LD_LIBRARY_PATH中。
④/etc/ld.so.conf.d建立自己的动态库路径的配置文件,然后重新ldconfig即可。

(实际情况,我们用的库都是别人的,成熟的库都采用直接安装到系统的方式。)

5、使用外部库:ncurses--基于终端的图形界面的库。

6、动态库是怎么被加载的。
①动态库在进程运行的时候,是要被加载的(静态库没有),这就是动态库具有可执行权限的原因。
②常见的动态库,被所有相关的可执行程序动态链接,都要使用动态库/共享库。所以,动态库在系统中加载之后,会被所有进程共享。
③动态库被加载的方式为:建立映射,从此往后我们执行的任何代码都是在我们的进程地址空间中进行执行。
④事实上,系统在运行中,一定会存在多个动态库,先描述再组织由OS管理起来。系统中,所有库的加载情况,OS都非常清楚。

7、程序加载前后地址:
①编译好没有加载前的程序是有地址的,其可执行数据区可以被分成很多段。形成可执行程序的编址已经形成了平坦模式(严格遵照地址空间的方式编码),因为编译器也要考虑操作系统。
注:可执行程序的地址为逻辑地址(磁盘中程序形成时所对应的地址,存偏移量)。
②程序加载后的地址进程:当可执行程序加载到内存的时候,每条指令天然的具有物理地址。
③执行程序形成的时候包含入口地址entry(逻辑地址)。
④CPU读取可执行程序时直接将entry加载到内部寄存器(EIP/PC)中,找到正文代码段从而找到页表,此时页表未建立对应的映射,触发缺页中断,于是程序被加载进来,具有了物理地址,从而页表也能填上对应的虚拟地址和物理地址,从而在物理内存中找到对应的指令代码。CPU内读取到的指令内部可能有数据,可能也有地址(虚拟地址)。(CPU读到指令中的地址全是虚拟地址)

8、动静态库的地址:
①问题:动态库在共享区过大,那具体映射到哪里呢?
动态库被加载到固定地址空间中的位置是不可能的。库只需在虚拟内存中任意位置加载,并让让自己内部函数不要采用绝对编址,只表示每个函数在库中的偏移量即可。
fPIC:产生位置无关码(直接用偏移量进行编址)。
②静态库为什么不谈加载,不谈与位置无关?
因为静态库已经拷贝在可执行程序里了,直接按绝对编址编码。

9、虚拟地址最终是怎么转换到物理地址的?
相关内容将会在后续章节讲解。
 

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

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

相关文章

混合云案例:利用 Databend Cloud 高效加速私有 Databend 的策略与实施

背景 Databend 是一款基于对象存储的存算分离湖仓产品&#xff0c;已成为云上大数据分析中高效且低成本的首选解决方案。目前&#xff0c;Databend 在多个用户场景中得到广泛应用&#xff0c;包括&#xff1a; 新媒体行业数据分析及大屏数据展示云上 CDH 替代以减少本地磁盘和…

Deep Image Prior

深度图像先验 论文链接&#xff1a;https://sites.skoltech.ru/app/data/uploads/sites/25/2018/04/deep_image_prior.pdf 项目链接&#xff1a;https://github.com/DmitryUlyanov/deep-image-prior Abstract 深度卷积网络已经成为一种流行的图像生成和恢复工具。一般来说&a…

web:[ZJCTF 2019]NiZhuanSiWei1

题目 点进题目&#xff0c;网页显示如下&#xff0c;需要代码审计 $_GET["text"]和$_GET["file"]来获取传入的两个参数text和file。使用isset()函数来检查$text变量是否已设置并且不为null。如果设置了并且不为null&#xff0c;则执行下面的逻辑。在下面的…

汽车电子 -- 车载ADAS之LCA(变道辅助系统)

相关法规文件: LCA: ISO 17387-2008 Intelligent transport systems — Lane change decision aid systems 一、变道辅助系统 LCA &#xff08;Lane Change Assist&#xff09; LCA 系统&#xff08;变道辅助系统&#xff09;监测后方相邻车道区域&#xff0c;如果有车辆在后…

《融合SCADA系统数据的天然气管道泄漏多源感知技术研究》误报数据识别模型开发

数据处理不作表述。因为我用的是处理后的数据&#xff0c;数据点这。 文章目录 工作内容1CC040VFD电流VFD转速压缩机转速反馈进出口差压 紧急截断阀开到位进出电动阀开到位发球筒电筒阀开到位收球筒电动阀开到位电动阀2005开到位越站阀开到位 工作内容2工作内容3 工作内容1 任…

Java小游戏 王者荣耀

GameFrame类 所需图片&#xff1a; package 王者荣耀;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.util.ArrayLis…

<JavaDS> 二叉树遍历各种遍历方式的代码实现 -- 前序、中序、后序、层序遍历

目录 有以下二叉树&#xff1a; 一、递归 1.1 前序遍历-递归 1.2 中序遍历-递归 1.3 后序遍历-递归 二、递归--使用链表 2.1 前序遍历-递归-返回链表 2.2 中序遍历-递归-返回链表 2.3 后序遍历-递归-返回链表 三、迭代--使用栈 3.1 前序遍历-迭代-使用栈 3.2 中序遍…

【Python3】【力扣题】367. 有效的完全平方数

【力扣题】题目描述&#xff1a; 【Python3】代码&#xff1a; 1、解题思路&#xff1a;Python函数。num的平方根 或者 num的0.5次幂。 知识点&#xff1a;float.is_integer(...)&#xff1a;判断浮点数的值是否等于整数。也可以&#xff1a;浮点数.is_integer()。 pow(a,b)&…

【SpringCloud】微服务的扩展性及其与 SOA 的区别

一、微服务的扩展性 由上一篇文章&#xff08;没看过的可点击传送阅读&#xff09;可知&#xff0c; 微服务具有极强的可扩展性&#xff0c;这些扩展性包含以下几个方面&#xff1a; 性能可扩展&#xff1a;性能无法完全实现线性扩展&#xff0c;但要尽量使用具有并发性和异步…

【Intel FPGA】D5005 使用笔记

项目总目标&#xff0c;在AFU中实现xx算法DDR 1.FPGA device &#xff1a;1SX280HN2F43E2VG 2 .硬件架构图 3.DDR信息 4.FIM &#xff08;FPAG Interface Manager&#xff09; The FIM contains the FPGA logic to support the accelerators, including the PCIe IP core, …

UDS 相关时间参数

文章目录 UDS 全部时间参数UDS 应用层诊断时间参数1、P2 Client P2 Server P2* Client P2* Server 图例2、S3 Client S3 Server 图例 UDS CNA-TP网络层时间参数1、N_As/N_Ar 图例2、N_Bs 图例3、 N_Br 图例4、N_Cs 图例N_Cr 图例 UDS 网络层流控制时间参数 UDS 全部时间参数 UD…

Java17(LTS Long Term Support)特性

支持JDK17的主流技术框架 spring framework 6.xspringboot 3.xkafka 3.0(不在支持jdk8)jenkins 2.357&#xff08;必须jdk11起步&#xff09;James Gosling表示赶紧弃用Java8&#xff0c;使用性能最好的JDK17Chart GPT也推荐JDK17&#xff0c;从长期到性能来说。 JDK17的特性 …

【古月居《ros入门21讲》学习笔记】15_ROS中的坐标系管理系统

目录 说明&#xff1a; 1. 机器人中的坐标变换 tf功能包能干什么&#xff1f; tf坐标变换如何实现 2. 小海龟跟随实验 安装 ros-melodic-turtle-tf 实验命令 运行效果 说明&#xff1a; 1. 本系列学习笔记基于B站&#xff1a;古月居《ROS入门21讲》课程&#xff0c;且使…

数据治理框架和成熟度模型

数据治理成熟度模型 一个企业的数据治理能力越高&#xff0c;所享受到数据治理带来的价值也会越多&#xff0c;如增加收入、减少成本、降低风险等。于是&#xff0c;很多企业想要准确地评估本公司的数据治理能力&#xff0c;可以利用数据治理成熟度模型方法&#xff0c;包括 D…

求和(打表题)

题目 打个表发现当 n 时答案为 p &#xff0c;否则为 1 &#xff0c;然后套板子。 #include <iostream> #include <algorithm> #include <vector> #include <cstring> #include <cmath>using namespace std;#define int long long using i64 …

直线(蓝桥杯)

直线 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 在平面直角坐标系中&#xff0c;两点可以确定一条直线。如果有多点在一条直线上&#xff0c; 那么这些点中任意两点确定的直线是同一条。 给定平面上 2 3 个…

万字解析设计模式之模板方法与解释器模式

一、模板方法模式 1.1概述 定义一个操作中算法的框架&#xff0c;而将一些步骤延迟到子类中&#xff0c;模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 例如&#xff0c;去银行办理业务一般要经过以下4个流程&#xff1a;取号、排队、办理具体业…

戴尔科技推出全新96核Precision 7875塔式工作站

工作站行业一直是快节奏且充满惊喜的。在过去25年中,戴尔Precision一直处于行业前沿,帮助创作者、工程师、建筑师、研究人员等将想法变为现实,并对整个世界产生影响。工作站所发挥的作用至关重要,被视为化不可能为可能的必要工具。如今,人工智能(AI)和生成式AI(GenAI)的浪潮正在…

【JavaEE初阶】认识线程、创建线程

1. 认识线程&#xff08;Thread&#xff09; 1.1 概念 1) 线程是什么 一个线程就是一个 "执行流". 每个线程之间都可以按照顺序执行自己的代码. 多个线程之间 "同时" 执行着多份代码. 举例&#xff1a; 还是回到我们之前的银⾏的例⼦中。之前我们主要描…

业务逻辑漏洞

业务逻辑漏洞 扫描器扫不出来 漏洞包括 暴力破解任意用户/密码登陆短信/邮箱轰炸验证码绕过/爆破/重放/回传用户名/手机号枚举(用户名枚举&#xff1a;当用户登录时&#xff0c;显示用户名不存在&#xff0c;或密码不正确&#xff0c;两个其中一个不正确就称为用户名枚举)越…