跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Shell / Bash

Linux 从硬件硬盘到文件系统的全面过渡

探讨了 Linux 环境下从物理硬盘结构到文件系统的演进过程。首先介绍了机械磁盘的物理组成,包括盘片、磁头、磁道、扇区和柱面,并解释了 CHS 与 LBA 寻址方式的原理及转换逻辑。随后阐述了操作系统如何将磁盘抽象为块设备,通过分区管理存储空间。最后深入解析了文件系统的核心概念,特别是 inode 索引节点在存储文件元数据中的作用,以及文件名与文件内容的分离存储机制。

静心发布于 2026/3/16更新于 2026/8/848 浏览
Linux 从硬件硬盘到文件系统的全面过渡

前提引入

**文件=内容 + 属性,这是从单个文件的角度。但是有很多文件,我们可以在宏观上把文件分为被打开的文件和没有被打开的文件;而被打开的文件在内存中方便管理,没有被打开的文件在磁盘里。

没有打开的文件肯定是很多的,那这么多的文件在磁盘中怎么被我们找到呢?从现阶段的认知,文件是一种目录结构,目录结构是树状的,需要路径(绝对、相对),文件存到磁盘上,最基本的诉求就是:就是被找到。而研究上面这些需求,要完成以特定的结构组织管理文件和帮我们找到文件就是文件系统做的事情!!!**

1. 理解硬件

磁盘 - 服务器 - 机柜 - 机房

机械磁盘是计算机中唯一的机械设备,外设慢容量大,价格便宜。

磁盘物理结构

磁盘存储结构

磁道是同心圆。

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

三片六面,六个磁头,磁头在传动臂的带动下,共进退!!!

磁盘写入的时候,是向柱面进行批量写入的!!!

如何定位一个扇区呢?可以先定位磁头(header)确定磁头要访问哪一个柱面 (磁道)(cylinder),定位一个扇区 (sector)。文件 = 内容 + 属性,都是数据,无非就是占据那几个扇区的问题!能定位一个扇区了,能不能定位多个扇区呢?能

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

细节:传动臂上的磁头是共进退的 (柱面(cylinder),磁头(head),扇区(sector),显然可以定位数据了,这就是数据定位 (寻址) 方式之一,CHS 寻址方式。

📌 CHS 寻址对早期的磁盘非常有效,知道用哪个磁头,读取哪个柱面上的第几扇区就可以读到数据了。但是 CHS 模式支持的硬盘容量有限,因为系统用 8bit 来存储磁头地址,用 10bit 来存储柱面地址,用 6bit 来存储扇区地址,而一个扇区共有 512Byte,这样使用 CHS 寻址一块硬盘最大容量为 256 * 1024 * 63 * 512B = 8064 MB(1MB = 1048576B)(若按 1MB=1000000B 来算就是 8.4GB)

磁盘的逻辑结构

理解过程

磁带上面可以存储数据,我们可以把磁带'拉直',形成线性结构。卷起来,就是同心圆,拉出来,就是一个线性结构!!!**

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

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

真实过程

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

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

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

即:一维数组

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

柱面上的每个磁道,扇区个数是一样的,可以理解成二维数组。整个盘:

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

所以,每一个扇区都有一个下标,我们叫做 LBA(Logical Block Address) 地址,其实就是线性地址。所以怎么计算得到这个 LBA 地址呢?LBA,1000,CHS 必须要! LBA 地址转成 CHS 地址,CHS 如何转换成为 LBA 地址。OS 只需要使用 LBA 就可以了!!LBA 地址转成 CHS 地址,CHS 如何转换成为 LBA 地址。谁做啊??磁盘自己来做!固件 (硬件电路,伺服系统)

CHS && LBA 地址

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

每磁道扇区数 + 扇区号 S - 1 即:LBA = 柱面号 C
每磁道扇区数) + 磁头号 H

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

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

2. 引入文件系统

引入'块概念'

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

注意:

• 磁盘就是一个三维数组,我们把它看待成为一个'一维数组',数组下标就是 LBA,每个元素都是扇区

• 每个扇区都有 LBA,那么 8 个扇区一个块,每一个块的地址我们也能算出来。

• 知道 LBA:块号=LBA/8 • 知道块号:LAB=块号*8+n.(n 是块内第几个扇区)

引入'分区'概念

其实磁盘是可以被分成多个分区(partition)的,以 Windows 观点来看,你可能会有一块磁盘并且将它分区成 C,D,E 盘。那个 C,D,E 就是分区。分区从实质上说就是对硬盘的一种格式化。但是 Linux 的设备都是以文件形式存在,那是怎么分区的呢?柱面是分区的最小单位,我们可以利用参考柱面号码的方式来进行分区,其本质就是设置每个区的起始柱面和结束柱面号码。此时我们可以将硬盘上的柱面(分区)进行平铺,将其想象成一个大的平面,如下图所示:

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

引入'inode'概念

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

每行包含 7 列:模式 硬链接数 文件所有者 组 大小 最后修改时间 文件名 ls -l 读取存储在磁盘上的文件信息,然后显示出来

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

user@host:~/test$ stat code.c 
File: code.c Size: 1744 Blocks: 8 IO Block: 4096 regular file Device: fc01h/64513d Inode: 547045 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 1002/ user) Gid: ( 1002/ user) Access: 2025-08-13 16:25:18.011548344 +0800 Modify: 2025-08-13 16:25:18.011548344 +0800 Change: 2025-08-13 16:25:18.015548373 +0800 Birth: 2025-08-13 16:25:18.011548344 +0800

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

每一个文件都有对应的 inode,里面包含了与该文件有关的一些信息。为了能解释清楚 inode,我们需要是深入了解一下文件系统。注意:Linux 下文件的存储是属性和内容分离存储的。Linux 下,保存文件属性的集合叫做 inode,一个文件,一个 inode,inode 内有一个唯一的标识符,叫做 inode 号

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

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) 
备注:EXT2_N_BLOCKS = 15

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

结束语

我们已经知道硬盘是典型的'块'设备,操作系统读取硬盘数据的时候,读取的基本单位是'块'。'块'又是硬盘的每个分区下的结构,难道'块'是随意的在分区上排布的吗?那要怎么找到'块'呢?还有就是上面提到的存储文件属性的 inode,又是如何放置的呢?文件系统就是为了组织管理这些的!!!

目录

  1. 前提引入
  2. 1. 理解硬件
  3. 磁盘 - 服务器 - 机柜 - 机房
  4. 磁盘物理结构
  5. 磁盘存储结构
  6. 磁盘的逻辑结构
  7. 理解过程
  8. 真实过程
  9. CHS && LBA 地址
  10. 2. 引入文件系统
  11. 引入“块概念”
  12. 引入“分区”概念
  13. 引入“inode”概念
  14. 结束语
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Neo4j 图数据库整合 MGeo:构建智能地理知识网络
  • Java 多线程并发编程:并发容器与线程协作实战
  • 未来八大最具潜力行业深度解析与技术趋势
  • AIGC 在现代教育技术中的应用与实现
  • Cursor 辅助开发 Web 版背单词应用实战
  • Java 抽象类详解:从理论到实践
  • whisper.cpp ggml-large-v3.bin 模型文件获取与使用
  • 注意力机制与 Transformer 模型实战
  • Python 办公自动化实战:批量处理 Excel、Word 与 PPT
  • 机场出租车调度问题数学建模实战解析(含 Python 模拟代码)
  • 网络安全面试核心题库:Web 安全、内网防御与等保测评详解
  • Android 离线语音识别实践:基于 Whisper 与 TensorFlow Lite 实现本地转录
  • AI 大模型在各国政务领域应用深度研究报告
  • Deep Java Library:Java 开发者实现 AI 功能的框架
  • C++ 基础语法与核心编程知识点总结
  • C/C++ 线程池详解
  • AHP-LLM 在 AI 辅助开发中的实践:从算法选择到工程落地
  • Kubernetes CronJob 定时任务详解
  • Alpine Linux apk 包管理器使用指南
  • PyCharm 中 GitHub Copilot 插件安装与配置指南

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online