『 Linux 』文件系统

文章目录

    • 磁盘构造
      • 磁盘抽象化
    • 磁盘的寻址方式
    • 磁盘控制器
    • 磁盘数据传输
    • 文件系统
      • Inode
      • 数据块(Data Blocks)
      • 超级块(SuperBlock)
      • 块组描述符(Group Descriptor)


磁盘构造

请添加图片描述

磁盘内部构造由磁头臂,磁头,主轴,盘片,盘面,磁道,柱面,扇区构成;

  • 磁头臂控制磁头的移动,可以精确地定位到磁盘上的特定磁道;
  • 磁头负责读取和写入数据;在读取数据时,磁头会检测盘片表面的磁性变化;在写入数据时,磁头会改变盘片表面的磁性,以存储数据;
  • 主轴带有马达,使盘片高速旋转;这种旋转允许磁头访问盘片上的任意位置;
  • 盘片数据存储的介质,通常有多个盘片叠加在一起,每个盘片有两个盘面;
  • 盘面盘片的每一面,用于存储数据;每个盘面都配备有对应的磁头;
  • 磁道盘面上的同心圆,数据以磁道为单位进行组织;每个磁道可以进一步被分割成多个扇区;
  • 柱面由所有盘面上相同磁道号的磁道组成;设想如果磁盘的多个盘片沿主轴方向穿透,形成的圆柱形结构即为柱面;
  • 扇区磁道进一步划分的单位,是磁盘存储数据的最小物理单元;每个扇区通常存储512字节或更多的数据;


磁盘抽象化

请添加图片描述

磁带设备的存储最终数据将被存储到磁带上;

将磁带拉直可以将其看成连续不断的空间;

将磁盘盘面进行抽象化;

由于盘片的高速转动+磁头臂带动磁头的移动可以将其看成是一个螺旋的运动;

螺旋化后拉直为一个以扇区为最小单位的连续不断的空间;

与磁带不同,磁带的访问为顺序访问,磁盘的访问通过盘片的高速旋转+磁头臂带动磁头可以进行随机访问;


磁盘的寻址方式

请添加图片描述

  • CHS(Cylinder-Head-Sector)寻址

    CHS寻址方式使用柱面号,磁头号和扇区号来定位磁盘上的数据;

    每个地址由三个部分组成:柱面号( C ),磁头号( H )和扇区号( S );

    • 柱面号( C ):表示磁盘上的柱面,柱面是所有盘片上相同半径的磁道的集合(从0开始编号);
    • 磁头号( H ):表示盘片上的磁头,磁头用于读取和写入数据(从0开始编号);
    • 扇区号( S ):表示磁道上的扇区,扇区是数据存储的最小单位(从1开始编号);
  • LBA(Logical Block Addressing)寻址

    LBA寻址方式使用逻辑块地址定位磁盘上的数据;

    每个逻辑块地址是一个唯一的整数,表示磁盘上的一个逻辑块(这里指扇区);

    • 逻辑块地址(LBA):表示磁盘上的一个逻辑块,逻辑块是数据存储的基本单位;
    • LBA寻址方式将整个磁盘视为一个连续的逻辑块数组,每个逻辑块都有一个唯一的地址;

因物理原因, LBA(Logical Block Addressing) 寻址最终以算法转换为 CHS(Cylinder-Head-Sector) 寻址;

  • LBA寻址转换为CHS寻址公式

    • 柱面号( C )

      C = LBA / ( H * S );
      
    • 磁头号( H )

      H = ( LBA / S ) % H;
      
    • 扇区号( S )

      S = ( LBA % S ) + 1; #CHS中扇区号从1开始计算
      
    • 例:

      • 磁盘有3盘片(6盘面);
      • 每个盘面有20000个扇区;
      • 每个盘面有50个磁道;
      • 每个磁道有400个扇区;
      • 需要访问的扇区编号(LBA)为28888;

      柱面号的计算:28888 / ( 50 * 400 ) = 1;

      相对扇区计算:28888 % ( 50 * 400 ) = 8888;

      磁道编号计算:8888 / 400 = 22;

      磁道上相对扇区编号:8888 % 400 = 88;

      结果:

      • 盘面编号:1;
      • 磁道编号:22;
      • 扇区编号:89(从1开始编号);

CHS寻址方式逆向得到LBA编号;


磁盘控制器

请添加图片描述

磁盘硬件中存在磁盘控制器(物理硬件);

  • 磁盘控制器的功能:
    • 数据传输
    • 执行命令
    • 错误检测和纠正
    • 缓存管理

在磁盘控制器中存在一系列的寄存器(硬件):命令寄存器,数据寄存器,状态寄存器,地址寄存器等;

  • 命令寄存器

    用于存储来自计算机的操作命令;

  • 数据寄存器

    用于暂存从计算机写入磁盘的数据,或者从磁盘读取的数据;

  • 状态寄存器

    用于指示当前磁盘的状态,以及最近一次操作的结果;

  • 地址寄存器

    用于指定数据在磁盘上的位置,如扇区号或磁道号;

同时在磁盘硬件中为用户提供了一系列的 接口/串口 ;

接口/串口 作为驱动程序与磁盘控制器之间的桥梁,操作系统将通过磁盘接口(接口/串口)间接调用磁盘控制器从而操作磁盘;


磁盘数据传输

请添加图片描述

计算机中存在一种允许外部设备直接与系统内存进行数据传输的硬件组件DMA;

DMA(Direct Memory Access,直接内存访问);

DMA在进行数据传输时无需经过CPU因此可以减少CPU负担;

假设用户请求创建一个名为newfile.txt新文件并写入数据:

  • 用户请求

    用户请求或进程调用open("newfile.txt", O_CREAT | O_WRONLY);

  • 系统调用处理

    CPU将系统调用转发给OS;

    OS内核文件系统模块接收请求;

  • 文件系统操作

    文件系统将维护对应的结构体并为其分配数据块;

  • 数据写入

    用户或应用程序调用write进行数据写入;

    文件系统写入分配的数据块;

  • DMA配置

    OS配置DMA控制器设置源地址和目标地址并启动DMA传输;

  • 驱动程序操作

    驱动程序将写入命令和数据块地址发送给磁盘控制器;

    驱动程序处理终端和状态信息;

  • 磁盘控制器操作

    磁盘控制器接收写入命令并解析;

    磁盘控制器通过DMA从内存读取数据并写入磁盘扇区;

    磁盘控制器报告状态;


文件系统

请添加图片描述

操作系统通常无法直接管理巨大的磁盘空间,因此需要对磁盘进行分区(类比Windows中对C,D,E,F盘的分区);

分区的方式一般通过操作系统维护其struct结构体即可;

struct partion{int start;int end;//...
}

而实际每个分区的大小也会比较大,需要继续对分区进行区分管理;

一般情况下每个分区都由以下组成:

  • 启动块(Boot Block)

    一般情况下BootBlock为引导块,只存在于系统盘当中;

    但有些情况也会存在其他分区当中;

    存在该块的分区一般被称为引导分区;

  • 块组(Block group)

    每个分区由若干个块组组成,由Blockgroup 0Blockgroup n;

    块组是文件系统重最基本的管理单元,每个块组包含多个数据块,Inode表和其他元数据;

(该图为演示,与内核空间映像存在差异)

块组中所包含的多个数据块即为文件系统;

每个块组通常包含以下几个部分:

  • 超级块(Superblock)

    • 存储文件系统的全局元数据;
  • 块组描述符表(Group Descriptor Table)

    • 存储每个块组的描述符,描述块组的元数据位置和状态;
  • 块位图(Block Bitmap)

    • 跟踪块组中数据块的使用情况;
  • Inode位图(Inode Bitmap)

    • 跟踪块组中Inode的使用情况;
  • Inode表(Inode Table)

    • 存储文件和目录的元数据;
    • Inode表中将存若干个Inode;
    • Inode用于存储文件基本属性(如文件类型,文件权限,拥有者,所属组等);
  • 数据块(Data Blocks)

    • 存储实际的文件和目录内容;

假设存在一个文件系统,其应包含以下块组:

struct superblock {int fs_size;  // 文件系统的大小int block_size;  // 块大小int free_blocks;  // 空闲块数量int free_inodes;  // 空闲Inode数量// 其他文件系统元数据
};struct group_descriptor {int block_bitmap;  // 块位图的起始位置int inode_bitmap;  // Inode位图的起始位置int inode_table;  // Inode表的起始位置int free_blocks;  // 块组中的空闲块数量int free_inodes;  // 块组中的空闲Inode数量// 其他块组元数据
};struct block_group {struct superblock sb;  // 超级块struct group_descriptor gd;  // 块组描述符char block_bitmap[128];  // 块位图char inode_bitmap[128];  // Inode位图struct inode inodes[1024];  // Inode表char data_blocks[4096][4096];  // 数据块
};struct inode {int file_type;  // 文件类型int permissions;  // 文件权限int size;  // 文件大小int block_pointers[12];  // 数据块指针// 其他文件元数据
};

磁盘中最小的存储单位为扇区,而在文件系统中最小的单位为 文件系统块 ;

存储数据的数据块中存在若干个 文件系统块 ;

文件系统块的大小必须 >= 扇区大小,一般最常用为4kb;

  • 在数据的存储中,一般只有最后一个文件系统块会产生空间浪费:

    假设一个文件的的大小为5kb,将会为其分配两个文件系统块用于存储,其中第二个块为最后一个块将浪费3kb的空间;


Inode

请添加图片描述

在Linux中,文件的内容与文件的属性构成一个完整的文件;

其中文件的内容与文件的属性是分开管理的;

  • 文件的内容管理在数据块(Data Blocks)中
  • 文件的属性管理在Inode表中的Inode中;

Inode可以看作是一个结构体,其包含一个文件的所有属性:

struct inode {uint16_t i_mode;        // 文件类型和权限uint16_t i_uid;         // 文件所有者的用户IDuint32_t i_size;        // 文件大小(字节)uint32_t i_atime;       // 最后访问时间uint32_t i_ctime;       // 创建时间uint32_t i_mtime;       // 最后修改时间uint32_t i_dtime;       // 删除时间uint16_t i_gid;         // 文件所属组的组IDuint16_t i_links_count; // 链接计数uint32_t i_blocks;      // 文件占用的块数uint32_t i_flags;       // 文件标志uint32_t i_block[15];   // 数据块指针// 其他文件系统特定的信息
};

其中每个Inode都在对应的文件系统中存在一个唯一编号(不同文件系统之间的Inode编号可以重复);

在Linux当中可以采用ls -li获取其Inode编号;

$ ls -li
total 0
2360117 -rw-rw-r-- 1 _XXX _XXX 0 Jun  1 18:02 newfile1.c
2360116 -rw-rw-r-- 1 _XXX _XXX 0 Jun  1 18:00 newfile.c

其中在每个块组中都存在一个Inode位图(Inode Bitmap)来跟踪该文件系统中的Inode的使用情况(利用位图可以大大节省跟踪时所使用的空间);

当需要访问一个文件时文件系统将根据Inode中的编号查找文件的目录和数据块指针从而访问文件的实际数据;

  • 文件的文件名不存在于Inode之中,而是单独存放在目录的数据结构当中

    每个目录在文件系统当中被视为一个特殊的文件,其自身拥有一个Inode与数据块;

    目录中的数据块保存了文件名与对应Inode编号的映射关系,这些映射关系被称为目录条目;

    • 目录条目的结构演示

      struct directory_entry {uint32_t inode_number;  // Inode编号char file_name[256];    // 文件名
      };
      

      当通过文件名访问文件时文件系统将会执行以下步骤:

      假设文件路径为/home/user/file.txt;

      • 根目录(/)

        查找根目录的Inode(通常为Inode2);

        在根目录的数据块中查找home目录的目录条并获取其Inode编号;

      • home目录

        查找home目录的Inode;

        home目录的数据块中,查找user目录的目录条目并获取其Inode编号;

      • user目录

        查找user目录的Inode;

        user目录的数据块中,查找file.txt的目录条目并获取其Inode编号;

      • file.txt文件

        查找file.txt的Inode;

        通过Inode中的数据块指针访问其文件的实际数据;


数据块(Data Blocks)

请添加图片描述

数据块中存在若干个文件系统块;

在文件系统中的块位图(Bolck Bitmap)即为跟踪当前文件系统中数据块内各个文件系统块的使用情况;

在Inode中存在一组数据块指针数组,一般情况这个指针数组的大小为15;

这个指针数组中包含了三种数据块指针:

  • 直接指针(Direct Pointers)
    • 通常有12个直接指针,每个直接指针直接指向一个数据块(下标0-11)。
    • 直接指针用于存储文件的前12个数据块。
  • 单重间接指针(Single Indirect Pointer)
    • 指向一个间接块,间接块中包含指向数据块的指针(下标12)。
    • 单重间接指针用于存储更多的数据块。
  • 双重间接指针(Double Indirect Pointer)
    • 指向一个双重间接块,双重间接块中包含指向间接块的指针,间接块中再包含指向数据块的指针(下标13)。
    • 双重间接指针用于存储更多的数据块。
  • 三重间接指针(Triple Indirect Pointer)
    • 指向一个三重间接块,三重间接块中包含指向双重间接块的指针,双重间接块中再包含指向间接块的指针,间接块中再包含指向数据块的指针(下标14)。
    • 三重间接指针用于存储更多的数据块。

可以将其中的数据块指针数据看成是一种树状结构;

删除一个文件的本质是删除其对应文件系统中的Block Bitmap以及相关映射删除(所以理论上数据的删除可以被修复),当需要再此使用时只需要对文件系统块对应的内容进行覆盖即可;


超级块(SuperBlock)

请添加图片描述

超级块中包含了当前文件系统中的全局信息和元数据(文件系统大小,块大小,空闲块数量等);

通常超级块位于文件系统的起始位置,每个块组中都可以存在一个超级块以便于在超级块损坏时可以进行对超级块的恢复;

超级块通常存在以下内容:

  • 文件系统元数据
    • 超级块包含文件系统的全局元数据,如文件系统的大小、块大小、空闲块数量、空闲Inode数量等。
    • 这些元数据用于文件系统的管理和操作。
  • 文件系统状态
    • 超级块包含文件系统的状态信息,如文件系统是否已挂载、是否已清除等。
    • 这些状态信息用于文件系统的维护和恢复。
  • 文件系统配置
    • 超级块包含文件系统的配置参数,如块大小、Inode大小、块组大小等。
    • 这些配置参数用于文件系统的初始化和操作。

超级块的结构示例如下:

struct superblock {uint32_t s_inodes_count;        // 文件系统中的Inode总数uint32_t s_blocks_count;        // 文件系统中的块总数uint32_t s_r_blocks_count;      // 保留块总数uint32_t s_free_blocks_count;   // 空闲块总数uint32_t s_free_inodes_count;   // 空闲Inode总数uint32_t s_first_data_block;    // 第一个数据块的块号uint32_t s_log_block_size;      // 块大小(以2的幂次表示)uint32_t s_log_frag_size;       // 碎片大小(以2的幂次表示)uint32_t s_blocks_per_group;    // 每个块组的块数uint32_t s_frags_per_group;     // 每个块组的碎片数uint32_t s_inodes_per_group;    // 每个块组的Inode数//...// 其他文件系统特定的信息
};

块组描述符(Group Descriptor)

请添加图片描述

块组描述符用于描述每个块组的元数据位置和状态;

其一般包含了所有块组的描述符,其中每个块组都有一个对应的块组描述符;

  • 块组描述符的作用

    • 描述块组元数据的位置

      块组描述符一般包含组内重要的元数据(块位图,Inode位图,Inode表)的起始位置;

      通过快描述符使得文件系统可以快速定位组内元数据;

    • 跟踪块组的状态

      块组描述符包含块组内空闲块和空闲Inode的数量;

      这些信息一般用于文件系统的管理和优化;

块组描述符的结构示例:

struct group_descriptor {uint32_t block_bitmap;  // 块位图的起始位置uint32_t inode_bitmap;  // Inode位图的起始位置uint32_t inode_table;   // Inode表的起始位置uint16_t free_blocks_count; // 块组中的空闲块数量uint16_t free_inodes_count; // 块组中的空闲Inode数量uint16_t used_dirs_count;   // 块组中的已使用目录数量// 其他块组元数据
};

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

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

相关文章

测试工具fio

一、安装部署 fio是一款优秀的磁盘IO测试工具,在Linux中比较常用于测试磁盘IO 其下载地址:https://brick.kernel.dk/snaps/fio-2.1.10.tar.gz 或者登录其官网:http://freshmeat.sourceforge.net/projects/fio/ 进行下载。 tar -zxvf fio-…

PCL 二维凸包切片法计算树冠体积

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 1、原理概述 二维凸包法是先将树冠等间隔分层切片,如图(e)采用二维凸包算法对每层…

ABP框架+Mysql(二)

展示页面--图书列表页面 本地化 开始的UI开发之前,我们首先要准备本地化的文本(这是你通常在开发应用程序时需要做的).本地化文本在前端页面会常用。 本地化文本位于 Acme.BookStore.Domain.Shared 项目的 Localization/BookStore 文件夹下: 打开 en.json (英文翻译)文件并更…

Superset二次开发之Github项目推送到GitLab仓库

以下是从GitHub克隆Superset项目并将其推送到GitLab的详细操作步骤 lab 地址: xxx lab 配置: 生成SSH密钥 ssh-keygen -t rsa -b 4096 -C "邮箱地址" 默认情况下密钥会生成在~/.ssh (/c/Users/Administrator/.ssh/id_rsa)目录下。 公钥添加到GitLab: 打开公钥文件…

音视频开发—FFmpeg打开麦克风,采集音频数据

文章目录 1.使用命令行实现采集PCM数据2.使用代码实现3.播放PCM4.PCM转换为WAV 1.使用命令行实现采集PCM数据 确保你的系统有FFmpeg安装。你可以通过在终端运行ffmpeg -version来检查是否已安装。 找出你的麦克风设备名。在Linux中,你可以使用arecord -l命令列出所…

Java实战:从文件读出学生列表

本实战项目的目标是从文本文件中读取学生列表,并验证读取过程的正确性通过单元测试。 创建静态方法 实现一个名为readStudentsFromFile的静态方法,该方法接收一个文件路径作为参数。创建一个Student对象的列表,用于存储从文件中读取的学生信息…

使用PyCharm 开发工具创建工程

一. 简介 前面学习了 安装 python解释器。如何安装python的一种开发工具 PyCharm。 本文来简单学习一下,如何使用 PyCharm 开发工具创建一个简单的 python工程。 二. PyCharm 开发工具创建一个工程 1. 首先,首先打开PyCharm 开发工具。选择 创建一…

2024-6-1 石群电路-20

2024-6-1,星期六,18:24,天气:晴,心情:晴。已经到学校啦,本来打算今天休息一天不更了,但是觉得可以更新完再休息,没有这么累,哈哈哈哈,这就不得不说…

长安链使用Golang编写智能合约教程(二)

长安链2.3.0的go合约虚拟机和2.3.0以下的不兼容,编译的方式也有差异,所以在ide上做了区分。 教程三会写一些,其他比较常用SDK方法的解释和使用方法 教程一:(长安链2.1.的版本的智能合约) 教程三&#xff…

排序方法——堆排序

文章目录 一、堆的概念二、向下调整法三、堆排序建堆排序 四、 完整代码 一、堆的概念 堆的概念:一个按照完全二叉树的储存方式存储的一维数组我们称之为堆。   堆可以分为大堆和小堆:   大堆:二叉树中父亲节点的值都比自己的孩子节点的…

阿里云部署nodejs

目录 1、安装node.js 1-1 进入opt/software 1-2 下载node.js安装包 1-3 解压 2 配置环境变量 2-1 vim中配置环境变量 2-2 命令行中保存环境变量 2-3 检查安装版本 2-3 更换镜像 3、上传node.js项目 1-1 启动项目 1-2 配置对应的安全组 ​编辑 4、pm2启动多个node项…

运维开发.Kubernetes探针与应用

运维系列 Kubernetes探针与应用 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263…

SQL—DQL(数据查询语言)之小结

一、引言 在前面我们已经学习完了所有的关于DQL(数据查询语言)的基础语法块部分,现在对DQL语句所涉及的语法,以及需要注意的事项做一个简单的总结。 二、DQL语句 1、基础查询 注意: 基础查询的语法是:SELE…

移动端性能测试(android/ios)

solox官网 https://github.com/smart-test-ti/SoloX solox简介 实时收集android/ios性能的工具,Android设备无需Root,iOS设备无需越狱。有效解决Android和iOS性能的测试和分析挑战。 solox安装 环境准备 python安装3.10以上的 python官网下载地址…

cocos creator 3.x实现手机虚拟操作杆

简介 在许多移动游戏中,虚拟操纵杆是一个重要的用户界面元素,用于控制角色或物体的移动。本文将介绍如何在Unity中实现虚拟操纵杆,提供了一段用于移动控制的代码。我们将讨论不同类型的虚拟操纵杆,如固定和跟随,以及如…

[AI OpenAI] 推出ChatGPT Edu

一种负担得起的解决方案,帮助大学将AI负责任地引入校园。 我们宣布推出ChatGPT Edu,这是一个专为大学设计的ChatGPT版本,旨在负责任地向学生、教职员工、研究人员和校园运营部署AI。ChatGPT Edu由GPT-4o提供支持,能够跨文本和视觉…

iPad里的图片如何导出 iPad的照片如何管理

我们的设备中充满了各种重要的照片和视频,特别是iPad,作为苹果公司的一款强大的平板电脑,它不仅能够捕捉生活中的精彩瞬间,还可以存储和展示我们珍贵的回忆。然而,随着照片数量的不断增加,有效地管理和导出…

IO流(1)

定义:存取和读取数据的解决方案 作用:用于读写数据(本地文件、网络) 分类: 一种是:输出流和输入流。 一种是:字节流和字符流。 字节流 字节流——FileOutputStream(字节输出流&…

【常见的六大排序算法】插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序

个人主页 创作不易,感谢大家的关注! 文章目录 前言 🎡一、插入排序🌲二、希尔排序🎉三、选择排序🎀四、冒泡排序🚘五、堆排序🛵六、快速排序1. Hoare版本2. 挖坑法3. 前后指针法4. 非…

VLAN的概念及优势

文章目录 VLAN的概念及优势分割广播域 广播域vlanVLAN的优势 VLAN的种类静态VLAN动态VLAN 静态VLAN的配置静态VLAN范围配置静态VLAN的步骤 TRUNK介绍与配置三层交换机转发原理三层交换技术mls基于CEF的MLSCEF是一种基于拓补转发的模型 三层交换机的配置层 VLAN的概念及优势 分…