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

【Linux】Ext系列文件系统(上)

目录

一、 理解硬件

1-1 磁盘

1-2 磁盘物理结构

1-3 磁盘的存储结构

1-4 如何定位一个扇区

1-4 磁盘的逻辑结构

1-4-1 理解过程

1-4-2 真实过程

1-5 CHS && LBA地址

二、文件系统

2-1 "块"概念

2-2 "分区"概念

2-3 "inode"概念


个人主页:uyeonashi-CSDN博客

一、 理解硬件

1-1 磁盘

基本结构

  • 盘片:是存储数据的介质,一般由铝合金或玻璃等材料制成,表面涂有磁性材料。盘片通常有多个,它们叠放在一起,安装在主轴上,能够高速旋转。
  • 磁头:负责读取和写入数据。每个盘片的上下两面都有一个磁头,磁头通过移动臂在盘片表面移动,寻找到正确的位置来进行数据的读写操作。磁头与盘片之间的距离非常小,通常只有几微米甚至更小,以实现高精度的数据读写。
  • 电机:包括主轴电机和音圈电机。主轴电机用于驱动盘片以恒定的速度旋转,常见的转速有 5400 转 / 分钟、7200 转 / 分钟等。音圈电机则负责控制磁头的移动,使磁头能够快速、准确地定位到需要读写数据的位置。
  • 控制电路:主要由硬盘控制器、缓存控制器等组成。硬盘控制器负责与计算机的其他部件进行通信,协调数据的- 传输和存储操作;缓存控制器管理硬盘的缓存,提高数据的读写性能。
  • 缓存:是硬盘中的高速内存区域,用于临时存储即将被读写的数据。缓存的大小通常为几 MB 到几十 MB 不等,较大的缓存可以提高硬盘的数据读写速度和系统性能。

1-2 磁盘物理结构

数据写入:当计算机需要向硬盘写入数据时,操作系统会将数据发送到硬盘的缓存中。然后,磁头根据数据的存储地址,在盘片旋转的同时,通过电磁转换原理,将数据以磁性信号的形式记录在盘片的特定位置上。
数据读取:当计算机需要从硬盘读取数据时,磁头首先会根据数据的存储地址移动到相应的位置,然后随着盘片的旋转,磁头感应盘片上的磁性信号,并将其转换为电信号,再经过放大、解码等处理后,将数据传输到硬盘的缓存中,最后由缓存将数据发送给计算机的其他部件。

1-3 磁盘的存储结构

扇区:是磁盘存储数据的基本单位,512字节,块设备

扇区是磁盘存储数据的基本单位,是磁盘上的一个弧形区域。常见的扇区大小为 512 字节。扇区是数据在磁盘上存储的最小单元,计算机在向磁盘写入数据时,会将数据按扇区进行划分并存储;读取数据时,也以扇区为单位进行读取。
不同盘面(磁头)上相同位置的磁道组成一个柱面。在进行数据读写时,通常会按柱面、磁头、扇区的顺序来访问磁盘上的数据,这样可以充分利用磁盘的存储结构,提高数据访问的效率。

1-4 如何定位一个扇区

• 可以先定位磁头(header)
• 确定磁头要访问哪一个柱面(磁道)(cylinder)
• 定位一个扇区(sector)
• CHS地址定位

文件 = 内容+属性 都是数据,无非就是占据那几个扇区的问题!

因为扇区是存储数据的基本单位,可以通过定位多个扇区的方式访问数据与存储数据。

• 扇区是从磁盘读出和写入信息的最小单位,通常大小为512 字节。
• 磁头(head)数:每个盘片一般有上下两面,分别对应1个磁头,共2个磁头
• 磁道(track)数:磁道是从盘片外圈往内圈编号0磁道,1磁道...,靠近主轴的同心圆用于停靠磁头,不存储数据
• 柱面(cylinder)数:磁道构成柱面,数量上等同于磁道个数
• 扇区(sector)数:每个磁道都被切分成很多扇形区域,每道的扇区数量相同
• 圆盘(platter)数:就是盘片的数量
• 磁盘容量=磁头数 × 磁道(柱面)数 × 每道扇区数 × 每扇区字节数
• 细节:传动臂上的磁头是共进退的

柱面,磁头,扇区,显然可以定位数据了,这就是数据定位(寻址)方式之一,CHS寻址方式。

1-4 磁盘的逻辑结构

1-4-1 理解过程

磁带上面可以存储数据,我们可以把磁带“拉直”,形成线性结构

那么磁盘本质上虽然是硬质的,但是逻辑上我们可以把磁盘想象成为卷在一起的磁带,那么磁盘的逻辑存储结构我们也可以类似于:

这样每一个扇区,就有了一个线性地址(其实就是数组下标),这种地址叫做LBA

1-4-2 真实过程

一个细节:传动臂上的磁头是共进退的

柱面是一个逻辑上的概念,其实就是每一面上,相同半径的磁道逻辑上构成柱面。
所以,磁盘物理上分了很多面,但是在我们看来,逻辑上,磁盘整体是由“柱面”卷起来的。

所以,磁盘的真实情况是:
磁道:
某一盘面的某一个磁道展开:

即:一维数组
柱面:
整个磁盘所有盘面的同一个磁道,即柱面展开:

• 柱面上的每个磁道,扇区个数是一样的
• 这不就是二维数组吗

整盘:

整个磁盘不就是多张二维的扇区数组表(三维数组?)
所有,寻址一个扇区:先找到哪一个柱面(Cylinder) ,在确定柱面内哪一个磁道(其实就是磁头位置,Head),在确定扇区(Sector),所以就有了CHS。
我们之前学过C/C++的数组,在我们看来,其实全部都是一维数组:

所以,每一个扇区都有一个下标,我们叫做LBA(Logical Block Address)地址,其实就是线性地址。所以怎么计算得到这个LBA地址呢?

LBA,1000,CHS 必须要! LBA地址转成CHS地址,CHS如何转换成为LBA地址。
OS只需要使用LBA就可以了!!LBA地址转成CHS地址,CHS如何转换成为LBA地址。谁做啊??磁盘自己来做!固件(硬件电路,伺服系统)

1-5 CHS && LBA地址

CHS转成LBA:
• 磁头数*每磁道扇区数 = 单个柱面的扇区总数
• LBA = 柱面号C*单个柱面的扇区总数 + 磁头号H*每磁道扇区数 + 扇区号S - 1
• 即:LBA = 柱面号C*(磁头数*每磁道扇区数) + 磁头号H*每磁道扇区数 + 扇区号S - 1
• 扇区号通常是从1开始的,而在LBA中,地址是从0开始的
• 柱面和磁道都是从0开始编号的
• 总柱面,磁道个数,扇区总数等信息,在磁盘内部会自动维护,上层开机的时候,会获取到这些参数。

LBA转成CHS:
• 柱面号C = LBA // (磁头数*每磁道扇区数)【就是单个柱面的扇区总数】
• 磁头号H = (LBA % (磁头数*每磁道扇区数)) // 每磁道扇区数
• 扇区号S = (LBA % 每磁道扇区数) + 1
• "//": 表示除取整

所以:从此往后,在磁盘使用者看来,根本就不关心CHS地址,而是直接使用LBA地址,磁盘内部自己转换。所以:
从现在开始,磁盘就是一个 元素为扇区 的一维数组,数组的下标就是每一个扇区的LBA地址。OS使用磁盘,就可以用一个数字访问磁盘扇区了。

二、文件系统

2-1 "块"概念

os文件系统访问磁盘,不以扇区为单位进行访问。而是以“块”为单位进行访问。“块”一般为8kb。

其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个”块”(block)。
硬盘的每个分区是被划分为一个个的”块”。一个”块”的大小是由格式化的时候确定的,并且不可以更改,最常见的是4KB,即连续八个扇区组成一个 ”块”。”块”是文件存取的最小单位。

注意:
• 磁盘就是一个三维数组,我们把它看待成为一个"一维数组",数组下标就是LBA,每个元素都是扇区
• 每个扇区都有LBA,那么8个扇区一个块,每一个块的地址我们也能算出来。
• 知道LBA:块号 = LBA/8
• 知道块号:LAB=块号*8 + n. (n是块内第几个扇区)

2-2 "分区"概念

其实磁盘是可以被分成多个分区(partition)的,以Windows观点来看,你可能会有一块磁盘并且将它分区成C,D,E盘。那个C,D,E就是分区。分区从实质上说就是对硬盘的一种格式化。

柱面是分区的最小单位,我们可以利用参考柱面号码的方式来进行分区,其本质就是设置每个区的起始柱面和结束柱面号码。 此时我们可以将硬盘上的柱面(分区)进行平铺,将其想象成一个大的平面,如下图所示:

注意:柱面大小一致,扇区个位一致,那么其实只要知道每个分区的起始和结束柱面号,知道每
一个柱面多少个扇区,那么该分区多大,其实和解释LBA是多少也就清楚了.

2-3 "inode"概念

之前我们说过文件=数据+属性,我们使用 ls -l 的时候看到的除了看到文件名,还能看到文件元数据(属性)

[root@localhost linux]# ls -l
总用量 12
-rwxr-xr-x. 1 root root 7438 "9月 13 14:56" a.out
-rw-r--r--. 1 root root 654 "9月 13 14:56" test.c

每行包含7列:
模式、硬链接数、文件所有者、组、大小、最后修改时间、文件名

ls -l读取存储在磁盘上的文件信息,然后显示出来

其实这个信息除了通过这种方式来读取,还有一个stat命令能够看到更多信息

[root@localhost linux]# stat test.c
    File: "test.c"
    Size: 654         Blocks: 8      IO Block: 4096     普通文件
Device: 802h/2050d    Inode: 263715  Links: 1
Access: (0644/-rw-r--r--)     Uid: ( 0/ root)     Gid: ( 0/ root)
Access: 2017-09-13 14:56:57.059012947 +0800
Modify: 2017-09-13 14:56:40.067012944 +0800
Change: 2017-09-13 14:56:40.069012948 +0800

到这我们要思考一个问题,文件数据都储存在”块”中,那么很显然,我们还必须找到一个地方储存文件的元信息(属性信息),比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为”索引节点”。

每一个文件都有对应的inode,里面包含了与该文件有关的一些信息。为了能解释清楚inode,我们需要是深入了解一下文件系统。

📌 注意:
        • Linux下文件的存储是属性和内容分离存储的
        • Linux下,保存文件属性的集合叫做inode,一个文件,一个inode,inode内有一个唯一的标识符,叫做inode号

所以一个文件的属性inode长什么样子呢?

/*
 * Structure of an inode on the disk
 */
struct ext2_inode {
    __le16 i_mode;        /* File mode */
    __le16 i_uid;         /* Low 16 bits of Owner Uid */
    __le32 i_size;        /* Size in bytes */
    __le32 i_atime;       /* Access time */
    __le32 i_ctime;       /* Creation time */
    __le32 i_mtime;       /* Modification time */
    __le32 i_dtime;       /* Deletion Time */
    __le16 i_gid;         /* Low 16 bits of Group Id */
    __le16 i_links_count; /* Links count */
    __le32 i_blocks;      /* Blocks count */
    __le32 i_flags;       /* File flags */

    union {
        struct {
            __le32 l_i_reserved1;
        } linux1;

        struct {
            __le32 h_i_translator;
        } hurd1;

        struct {
            __le32 m_i_reserved1;
        } masix1;
    } osd1;               /* OS dependent 1 */

    __le32 i_block[EXT2_N_BLOCKS]; /* Pointers to blocks */
    __le32 i_generation;  /* File version (for NFS) */
    __le32 i_file_acl;    /* File ACL */
    __le32 i_dir_acl;     /* Directory ACL */
    __le32 i_faddr;       /* Fragment address */

    union {
        struct {
            __u8 l_i_frag;      /* Fragment number */
            __u8 l_i_fsize;     /* Fragment size */
            __u16 i_pad1;
            __le16 l_i_uid_high; /* these 2 fields */
            __le16 l_i_gid_high; /* were reserved2[0] */
            __u32 l_i_reserved2;
        } linux2;

        struct {
            __u8 h_i_frag;      /* Fragment number */
            __u8 h_i_fsize;     /* Fragment size */
            __le16 h_i_mode_high;
            __le16 h_i_uid_high;
            __le16 h_i_gid_high;
            __le32 h_i_author;
        } hurd2;

        struct {
            __u8 m_i_frag;      /* Fragment number */
            __u8 m_i_fsize;     /* Fragment size */
            __u16 m_pad1;
            __u32 m_i_reserved2[2];
        } masix2;
    } osd2;               /* OS dependent 2 */
};

/*
 * Constants relative to the data blocks
 */
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)

📌 再次注意:
• 文件名属性并未纳入到inode数据结构内部
• inode的大小一般是128字节或者256,我们后面统一128字节
• 任何文件的内容大小可以不同,但是属性大小一定是相同的


本篇完!


http://www.kler.cn/a/589689.html

相关文章:

  • 机器人触觉的意义
  • 解决 openeuler 系统 docker 下载慢,docker 镜像加速
  • Unix时间戳BKP备份寄存器RTC实时时钟
  • docker配置国内镜像站链接
  • 【嵌入式】ESP_01S智能家居:可二次开发式智能灯控/门禁,勾勒智能生活新图景
  • 【算法】 进制转换(附蓝桥杯真题) python
  • Elasticsearch面试题
  • Docker命令解析:加速你的容器化之旅(以Nginx为例)
  • 爬虫逆向:逆向中用到汇编语言详细总结
  • Pygame实现记忆拼图游戏7
  • 接口请求限制自定义注解
  • 机器学习核心概念解读
  • Webpack构建流程详解优化前端性能\Dev-Server与Proxy\网络攻击\HMR
  • 深入解析 Spring Boot 中的 FailureAnalyzer
  • C++菱形继承内存模型
  • ONENET数据可视化命令框下发命令使用
  • 内网环境安装dlv,本地远程调试go
  • 自动化实施的常用元件有哪几种?
  • hadoop-配置安装jdk
  • Linux目录结构以及文件操作