【Linux系统】理解硬件 | 引入文件系统

发布于:2025-07-27 ⋅ 阅读:(14) ⋅ 点赞:(0)

在基础IO中我们详细介绍了文件存储在文件描述符表中,也就是被打开的文件会被文件描述符表管理起来,那未被打开的文件存储在哪里呢?是怎么被找到的呢?这些问题我们会在后文中给出解释

1. 理解硬件

1.1 磁盘、服务器、机柜、机房

1. 磁盘(机械磁盘)

  • 是计算机中唯一的机械设备:机械磁盘是计算机系统中唯一的机械设备,因为它包含盘片、磁头等物理运动部件,而其他组件(如CPU或内存)是纯电子设备。这使其在计算机中独特,但也导致其速度较慢。
  • 是外设:磁盘被归类为外部存储设备(外设),因为它位于计算机主系统之外,负责永久性数据存储,与内存等内部组件不同。作为外设,它通过接口(如SATA)与主机连接。
  • :机械磁盘的读写速度较慢,主要原因是其机械结构:盘片需要旋转(由马达驱动),磁头需要物理移动来定位数据。这导致延迟较高(毫秒级),远低于固态硬盘或内存的速度。企业虽常用其存储数据,但其性能是瓶颈之一。
  • 容量大,价格便宜:机械磁盘的存储容量大(常见从数百GB到数TB),且单位存储成本低,适合存储大量数据(如企业备份或冷数据)。价格优势源于成熟技术和磁性材料的使用,而固态硬盘虽快但成本更高。

2. 服务器

  • 服务器是高性能计算机,用于运行应用和服务(如网站或数据库)。它们通常安装在机柜中,并放置在机房内。服务器运行时产生大量热量,需要高效散热(如风扇或空调),且依赖稳定电力供应以避免中断。
    • 服务器“运行起来就不会轻易关闭”,因此机房需确保散热和电力稳定。
    • 服务器机架和机柜行业涉及这些设备的部署和管理。

3. 机柜

  • 机柜(或机架)是用于集中存放和保护服务器、网络设备等的物理框架。它提供结构支撑、散热管理和电缆整理功能。机柜的设计影响设备密度和散热效率,是企业数据中心的基础设施。
    • 机柜行业专注于优化这些设备,以支持高密度服务器部署。

4. 机房

  • 机房是专门设计用于放置服务器、机柜等设备的房间。关键考虑因素包括:
    • 散热效果:服务器运行时发热量大,必须通过空调、通风系统等散热管理,防止设备过热损坏或性能下降。
    • 电力供应:需要稳定且冗余的电力(如UPS或发电机),避免停电导致数据丢失或服务中断。
    • 机房建设成本高,但对企业至关重要,尤其用于数据中心。

题外话

  1. 关于机房:如上所述,机房的核心需求是散热和电力。详细解释了原因:服务器热量积累可能导致硬件故障,而电力中断会引发服务不可用。因此,机房位置需优先考虑这些因素,以确保设备可靠运行。
  2. 关于磁盘和磁铁:磁盘使用磁性材料存储数据,类似于磁铁原理。说明磁盘“用磁来存储”,盘片上的磁性颗粒通过磁头(电磁铁)改变极性(N/S极)来记录0/1二进制数据。删除数据时,磁性状态未立即改变,因此数据可恢复。磁盘“由亿个小磁铁构成”,磁头通过改变NS极与计算机交互。磁头“充放电改变盘面南北极”写入数据,但磁头与盘面不直接接触,以防刮伤。磁盘在某些语境中被称为“磁盘”,因其磁性存储本质。

总结

  • 机械磁盘是计算机唯一的机械设备和外设,以容量大、价格便宜为优势,但速度慢。
  • 服务器是核心计算设备,依赖机柜和机房环境。
  • 机柜提供物理支撑和散热,机房确保稳定运行环境(散热和电力)。
  • 磁盘的磁性存储原理类似磁铁,利用极性变化记录数据。

1.2 磁盘物理结构

  1. 盘片(Platter)

    • 由铝制或玻璃基板覆盖磁性材料制成(如铁磁性涂层),用于存储数据 。
    • 多个盘片叠放组成磁盘组,围绕主轴高速旋转(典型转速为5400/7200/15000 RPM) 。
  2. 磁头(Read/Write Head)

    • 每个盘面对应一个磁头,采用“读写合一”的电磁感应设计:
      • 写入磁头:传统感应式,通过电流改变磁性颗粒极性(N/S极) 。
      • 读取磁头:现代磁盘多使用MR(磁阻)磁头,灵敏度更高 。
    • 磁头悬浮于盘面纳米级高度(不直接接触),通过传动臂移动定位 。
  3. 传动系统(Actuator Assembly)

    • 传动臂:承载磁头,沿盘片半径方向移动,定位目标磁道 。
    • 电动机:驱动主轴旋转盘片,保持恒定转速 。


1.3 磁盘的存储结构

  1. 磁道(Track)

    • 盘片表面的同心圆环,数据沿磁道存储 。
    • 相邻磁道间保留间隙(避免磁性干扰) 。
  2. 扇区(Sector)

    • 磁道被等分的弧段,是最小读写单元(传统大小为512B,现代磁盘支持4KB) 。
    • 每个扇区含数据区(存储数据)和间隙区(标识扇区边界) 。
  3. 柱面(Cylinder)

    • 所有盘面上相同半径的磁道组成的圆柱体(如0号磁道在所有盘面构成0号柱面) 。
    • 数据读写优化:同一柱面的数据无需移动传动臂即可通过切换磁头访问,减少寻道时间 。


1.4 磁盘的工作机制

  1. 数据读写流程

    • 寻道(Seeking) :传动臂移动磁头至目标磁道(耗时3~15ms) 。
    • 旋转延迟(Rotation) :盘片旋转至目标扇区下方(耗时2~4ms) 。
    • 数据传输:磁头读取/写入数据(速度极快,可忽略) 。
  2. 数据存储顺序

    • 柱面优先:先写满同一柱面的所有磁道(切换磁头),再移动至下一柱面(移动传动臂) 。
    • 扇区顺序:同一磁道按扇区编号顺序写入 。
  3. 性能瓶颈

    • 机械延迟:寻道与旋转延迟占访问时间90%以上(合计5~15ms),远低于内存/CPU的纳秒级速度 。
    • 优化策略
      • 批量读写连续扇区(减少寻道次数) 。
      • 磁盘调度算法(如电梯算法)优化磁头移动路径 。

如何定位一个扇区呢?

一、扇区定位的核心原理:CHS寻址

CHS寻址(Cylinder-Head-Sector)是一种通过物理坐标定位磁盘扇区的方法,其核心步骤如下:

  1. 定位磁头(Head) :选择具体盘面。
    • 每个盘面对应一个磁头(双面盘片有2个磁头),磁头号从0开始编号(如0号磁头对应上盘面)。
  2. 定位柱面(Cylinder) :确定磁道位置。
    • 所有盘面上相同半径的磁道构成一个柱面,编号从外圈向内递增(最外圈为0号柱面)。
    • 传动臂上的磁头共进退,因此同一时刻所有磁头位于同一柱面。
  3. 定位扇区(Sector) :在磁道上精确定位。
    • 每个磁道被划分为多个扇区(通常512字节),扇区编号从1开始(非0)。

示例:CHS地址 (0,0,1) 表示:

  • 0号柱面(最外圈磁道)
  • 0号磁头(第一个盘面)
  • 1号扇区(该磁道起始扇区)

二、CHS寻址的物理基础与数据结构

1. 磁盘物理结构关联性
组件 作用 与CHS的关联
磁头(Head) 读写数据,每盘面一个 直接对应H参数,选择盘面
柱面(Cylinder) 所有盘面同半径磁道的集合 对应C参数,定位磁道半径位置
扇区(Sector) 最小存储单元(512字节) 对应S参数,确定磁道内具体位置
2. 寻址过程的技术细节
  • 物理寻址流程
    1. 传动臂移动至目标柱面半径位置(耗时3~15ms)。
    2. 激活目标磁头,等待盘片旋转至目标扇区下方(旋转延迟2~4ms)。
    3. 读写数据(纳秒级)。
  • 地址表示规则
    • 柱面号(C)、磁头号(H)、扇区号(S)构成三元组
    • 早期系统用 24位二进制存储CHS:
      • 10位柱面号(最大1024柱面)
      • 8位磁头号(最大256磁头)
      • 6位扇区号(最大63扇区/磁道)。

三、多扇区定位与文件存储的实现

1. 文件数据的物理存储逻辑
  • 文件属性与内容均以二进制形式存储,占用一个或多个连续/离散扇区
  • 多扇区定位能力
    • CHS可定位任意单个扇区,通过组合多个CHS地址即可读写跨扇区文件。
    • 示例:读取占用10个扇区的文件时,操作系统按顺序访问10组CHS地址。
2. 磁盘容量的计算与限制
  • 容量公式

    容量 = 磁头数 × 柱面数 × 每磁道扇区数 × 512字节  
    
    • 举例:256磁头 × 1024柱面 × 63扇区 × 512B ≈ 8.4GB(按1MB=1,000,000B计)。
  • CHS的容量瓶颈

    • 24位地址空间上限仅支持8.4GB(柱面数≤1024,磁头数≤256,扇区数≤63)。
    • 根源:寄存器位数限制(10+8+6)无法表示更大地址。

 以上CHS寻址前提是:每个磁道上有同样数量的扇区 ,早期硬盘上也的确遵循这个。不过随着硬盘容量增加,盘面的数据密度也随之增加,单位面积中理论能容纳的二进制位数量有限。 理论
上,如果保持相同密度的话,盘片外圈能比内圈容纳更多数据。因此硬盘厂商们开始在盘面上将磁道划分出 区块(zone),外圈区块中的磁道可以比内圈区块中的磁道多放入一些扇区。这种方式生产出的硬盘叫 区位记录硬盘(Zone bit recoding, ZBR)


1.5 磁盘的逻辑结构

为解决CHS的容量限制,现代磁盘采用 LBA(Logical Block Addressing)

  • 原理

    • 将整个磁盘抽象为线性扇区数组,扇区从0开始连续编号。
    • 操作系统直接使用LBA号,磁盘控制器自动转换为物理CHS地址

柱面是一个逻辑上的概念,它由每个盘面上相同半径的磁道组合而成。虽然磁盘物理上由多个盘面组成,但从逻辑角度来看,整个磁盘可以被视为由这些"柱面"卷绕而成。

实际上,磁盘的工作原理是这样的:

磁道结构:

将盘面上的单个磁道展开来看:

即一维数组

柱面:

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

  • 每个柱面的磁道包含相同数量的扇区
  • 这不就是二维数组吗?

整盘:

整个磁盘本质上是由多张二维扇区表组成的(可以理解为三维数组结构)。

要定位一个扇区需要三步:首先确定柱面位置(Cylinder),然后在选定柱面上确定磁道位置(即磁头位置,Head),最后确定具体扇区(Sector)——这就是CHS寻址方式的由来。

正如我们学习C/C++数组时所了解的,从程序的角度来看,所有数组本质上都是一维结构。

每个扇区都有一个对应的编号,称为LBA(Logical Block Address)地址,实际上就是线性地址。那么,这个LBA地址是如何计算出来的呢?

现代操作系统只需使用LBA(逻辑块地址)即可完成磁盘访问!磁盘固件(包括硬件电路和伺服系统)会自动处理LBA与CHS(柱面-磁头-扇区)地址之间的双向转换,无需操作系统介入。

1.6 CHS && LBA地址

一、CHS 与 LBA 寻址的本质差异

特性 CHS(柱面-磁头-扇区) LBA(逻辑块地址)
定位方式 三维物理坐标(柱面号、磁头号、扇区号) 一维线性地址(连续编号的扇区索引)
抽象层级 直接对应磁盘物理结构 屏蔽物理细节,提供逻辑扇区视图
起始编号 扇区号从 1 开始,柱面/磁头从 0 开始 所有地址从 0 开始连续编号
容量限制 最大 8.4GB(24位地址限制) 支持 TB 级及以上(如 48位LBA)
使用场景 早期 BIOS/MBR 引导、磁盘控制器内部转换 现代操作系统、文件系统、UEFI 固件

核心矛盾
CHS 依赖磁盘物理参数(磁头数、柱面数、每磁道扇区数),而不同磁盘参数差异巨大,导致操作系统需适配无数硬件型号。LBA 通过逻辑抽象解决此问题,使上层软件仅关注线性扇区数组

CHS与LBA转换公式:

  1. CHS转LBA:

    • 单个柱面扇区数 = 磁头数 × 每磁道扇区数
    • LBA = 柱面号(C) × 单个柱面扇区数 + 磁头号(H) × 每磁道扇区数 + 扇区号(S) - 1
    • 注:扇区号从1开始计数,而LBA地址从0开始编号;柱面和磁道编号均从0开始

示例(Western Digital 硬盘参数:磁盘总磁头数(每柱面磁头数)=16, 每磁道扇区数=63
CHS (2, 3, 4) → LBA = (2×16×63) + (3×63) + (4-1) = 2016 + 189 + 3 = 2208

  1. LBA转CHS:

    • 柱面号(C) = LBA ÷ 单个柱面扇区数(取整)
    • 磁头号(H) = (LBA % 单个柱面扇区数) ÷ 每磁道扇区数(取整)
    • 扇区号(S) = (LBA % 每磁道扇区数) + 1

示例(参数同上,LBA=2208):

  • C = 2208 // (16×63) = 2208 // 1008 = 2
  • 余数 R1 = 2208 % 1008 = 192
  • H = 192 // 63 = 3
  • S = (192 % 63) + 1 = 3 + 1 = 4 → CHS (2, 3, 4) 

注意:磁盘内部自动维护总柱面数、磁道数和扇区总数等参数,系统启动时会获取这些信息。

层 级 角色 使用地址 说明
硬件层 磁盘控制器 CHS/LBA 自动转换 LBA → 物理CHS,对上层透明 
固件层 UEFI/GPT LBA 分区表直接记录起始/终止 LBA 
操作系统层 文件系统(ext4/NTFS) LBA 通过块设备接口读写逻辑扇区 
应用层 数据库/虚拟机 LBA 直接调用 read/write 系统调用

最终结论

  1. CHS 是磁盘物理结构的直接映射,LBA 是面向逻辑的抽象层。
  2. 转换公式的数学本质是三维坐标与一维线性空间的映射(受限于磁盘参数)。
  3. 现代系统中,磁盘 = 扇区的一维数组,LBA 是数组下标,CHS 仅存在于控制器内部转换层。
  4. 操作系统通过 磁盘总磁头数(每柱面磁头数)、每磁道扇区数 等参数初始化磁盘驱动,后续完全使用 LBA 操作设备 。

2. 引入文件系统

2.1 引入"块"概念

其实硬盘是典型的"块"设备,操作系统读取硬盘数据的时候,并不是直接以扇区为单位进行读取的。这是因为现代硬盘的扇区大小通常为512字节(较新的硬盘可能使用4KB扇区),如果以单个扇区为单位进行读取,会导致大量的I/O操作,严重影响系统性能。

为了提高效率,操作系统会一次性连续读取多个扇区,即读取一个"块"(block)。在大多数现代文件系统中:

  1. 块大小的典型值为4KB(即8个512字节的扇区)
  2. 块是文件系统进行I/O操作的最小单位
  3. 块大小在格式化时确定,之后不可更改

从磁盘寻址的角度来看:

  • 磁盘可以视为一个三维数组(柱面、磁头、扇区),但为了简化,我们可以将其抽象为一个一维数组
  • 每个扇区都有唯一的LBA(Logical Block Addressing)地址
  • 块地址可以通过LBA计算得出:
    • 已知LBA求块号:块号 = LBA / 8(当块大小为4KB时)
    • 已知块号求LBA:LBA = 块号 * 8 + n(n表示块内第n个扇区)


2.2 引入"分区"概念

磁盘可以被划分为多个分区(partition),这是对硬盘进行逻辑划分的一种方式。分区的本质是对硬盘的格式化,不同分区可使用不同文件系统(如NTFS、EXT4)。从用户角度来看:

  1. 在Windows系统中,分区表现为不同的驱动器(如C:、D:、E:等我们常说的盘)
  2. 在Linux系统中,分区表现为特殊的设备文件(如/dev/sda1、/dev/sda2等)

分区的基本原理:

  • 分区的最小单位是柱面(由多个磁道组成的圆柱形区域)
  • 每个分区通过起始柱面号和结束柱面号来定义
  • 分区信息记录在磁盘的分区表中(如MBR或GPT)

从寻址角度来看:

 操作系统通过分区表(如MBR)记录各分区的起止柱面,进而映射到LBA地址。由于柱面大小固定,且每个柱面包含的扇区数相同

  1. 只要知道:
    • 分区的起始柱面号
    • 结束柱面号
    • 每个柱面包含的扇区数
  2. 就可以计算出:
    • 分区的大小
    • 分区内任意位置的LBA地址

这种分区方式使得磁盘空间管理更加灵活,不同的分区可以使用不同的文件系统,也可以用于不同的用途(如系统分区、数据分区等)。

  


2.3 引入"inode"概念

在Linux系统中,文件由两部分组成:文件数据(内容)和文件属性(元数据)。当我们使用ls -l命令时,就能看到这些文件属性信息。让我们通过一个更详细的例子来理解:

ltx@hcss-ecs-d90d:~$ ls -l
total 16
-rw-rw-r--  1 ltx  ltx    71 Jul  8 16:45 code.c
drwxrwxr-x  2 ltx  ltx  4096 Jul 20 12:31 Linux_network
drwxrwxr-x 10 ltx  ltx  4096 Jul 23 23:07 Linux_system
drwxr-xr-x  3 root root 4096 Jul  7 14:21 mydir

这个输出实际上展示了7个关键属性:

  1. 文件类型和权限(模式):如"-rw-rw-r--"表示普通文件,所有者可读写,组用户可读写,其他用户只读
  2. 硬链接数:表示有多少个文件名指向这个inode
  3. 文件所有者:通常是创建该文件的用户
  4. 所属组:决定哪些用户可以访问该文件
  5. 文件大小:以字节为单位
  6. 最后修改时间:文件内容最后一次被修改的时间
  7. 文件名:用户可见的文件标识符

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

更详细的信息可以通过stat命令查看,它展示了文件系统中更底层的元数据:

ltx@hcss-ecs-d90d:~$ stat code.c
  File: code.c
  Size: 71        	Blocks: 8          IO Block: 4096   regular file
Device: fc01h/64513d	Inode: 142886      Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/     ltx)   Gid: ( 1000/     ltx)
Access: 2025-07-16 19:13:03.446155686 +0800
Modify: 2025-07-08 16:45:26.024247415 +0800
Change: 2025-07-08 16:45:26.028247456 +0800
 Birth: 2025-07-08 16:45:26.024247415 +0800

这里引出了inode的核心概念:在文件系统中,文件数据存储在"块"中,而元信息(包括上述所有属性)则存储在称为inode(索引节点)的数据结构中。每个文件都有一个对应的inode,其中包含以下关键信息:

  1. 文件类型和权限(i_mode)
  2. 所有者ID和组ID(i_uid, i_gid)
  3. 文件大小(i_size)
  4. 时间戳(访问/创建/修改时间)
  5. 链接计数(i_links_count)
  6. 文件数据块的位置(i_block[])
  7. 其他文件系统相关信息

可以通过ls -i命令查看文件的inode编号:

ltx@hcss-ecs-d90d:~$ ls -li
total 16
142886 -rw-rw-r--  1 ltx  ltx    71 Jul  8 16:45 code.c
148723 drwxrwxr-x  2 ltx  ltx  4096 Jul 20 12:31 Linux_network
148728 drwxrwxr-x 10 ltx  ltx  4096 Jul 23 23:07 Linux_system
150851 drwxr-xr-x  3 root root 4096 Jul  7 14:21 mydir

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

inode在文件系统中的组织形式可以用以下结构体表示(以ext2文件系统为例):

/*
* 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)

核心字段:

字段 含义 示例(stat命令输出)
i_mode 文件类型和权限(如-rw-r--r-- Access: (0664/-rw-rw-r--)
i_uid/i_gid 所有者和所属组ID Uid: (1000/ltx)
i_size 文件大小(字节) Size: 71
i_atime 最后访问时间 Access: 2025-07-16 19:13:03
i_mtime 最后修改时间 Modify: 2025-07-08 16:45:26
i_ctime 属性最后变更时间 Change: 2025-07-08 16:45:26
i_links_count 硬链接数量 Links: 1
i_blocks 占用的磁盘块数 Blocks: 8
i_block[] 文件数据块的指针数组 -
i_generation 文件版本(用于NFS) -

关于inode需要特别注意的几点:

  1. 文件名并不存储在inode中。文件名和inode编号的映射关系保存在目录文件中。
  2. inode大小通常是固定值(128或256字节),与文件内容大小无关。
  3. 每个inode都有一个唯一的编号,通过这个编号可以快速定位文件的元信息和数据块位置。
  4. inode中存储了指向文件数据块的指针,包括12个直接指针、1个一级间接指针、1个二级间接指针和1个三级间接指针(EXT2_N_BLOCKS=15)。

文件系统通过inode实现了高效的文件管理:

  • 通过inode编号可以快速定位文件属性和数据块位置
  • 硬链接机制允许多个文件名指向同一个inode
  • 权限管理基于inode中的用户/组ID和权限位
  • 文件访问时间等信息都记录在inode中

理解inode是理解Linux文件系统工作原理的关键,它解决了文件属性存储、快速访问和数据块定位等核心问题。

下一篇文章我们将详细介绍ext2文件系统


网站公告

今日签到

点亮在社区的每一天
去签到