禅与计算机 禅与计算机
首页
  • Java基础

    • 聊一聊java一些核心知识点
    • 聊聊java面向对象核心知识点
    • 聊聊Java中的异常
    • 聊聊Java中的常用类String
    • 万字长文带你细聊Java注解本质
    • 来聊聊Java的反射机制
    • 深入解析Java泛型的魅力与机制
    • Java集合框架深度解析与面试指南
    • Java常用集合类HashMap深度解析
    • LinkedHashMap源码到面试题的全解析
    • 深入解析CopyOnWriteArrayList的工作机制
    • Java基础IO总结
    • Java三大IO模型小结
    • Java BIO NIO AIO详解
    • Java进阶NIO之IO多路复用详解
    • Java8流式编程入门
    • 一文速通lambda与函数式编程
    • Java8函数式方法引用最佳实践
  • Java并发编程

    • Java并发编程基础小结
    • 深入理解Java中的final关键字
    • 浅谈Java并发安全发布技术
    • 浅谈Java并发编程中断的哲学
    • Java线程池知识点小结
    • 浅谈Java线程池中拒绝策略与流控的艺术
    • synchronized关键字使用指南
    • 深入源码解析synchronized关键字
    • 详解JUC包下的锁
    • 详解并发编程中的CAS原子类
    • LongAdder源码分析
    • AQS源码解析
    • 深入剖析Java并发编程中的死锁问题
    • Java并发容器总结
    • 详解Java并发编程volatile关键字
    • 并发编程ThreadLocal必知必会
    • CompletableFuture基础实践小结
    • CompletableFuture异步多任务最佳实践
    • 硬核详解FutureTask设计与实现
    • 线程池大小设置的底层逻辑与场景化方案
    • 来聊一个有趣的限流器RateLimiter
  • JVM相关

    • 从零开始掌握 JVM
    • JVM核心知识点小结
    • JVM指令集概览:基础与应用
    • JVM类加载器深度解析
    • JVM方法区深度解析
    • Java内存模型JMM详解
    • Java对象大小的精确计算方法
    • 逃逸分析在Java中的应用与优化
    • 从零开始理解JVM的JIT编译机制
    • G1垃圾回收器:原理详解与调优指南
    • JVM故障排查实战指南
    • JVM内存问题排错最佳实践
    • JVM内存溢出排查指南
    • 简明的Arthas使用教程
    • 简明的Arthas配置及基础运维教程
    • 基于Arthas Idea的JVM故障排查与指令生成
    • 基于arthas量化监控诊断java应用方法论与实践
    • 深入剖析arthas技术原理
  • 深入理解Spring框架

    • Spring 核心知识点全面解析
    • Spring核心功能IOC详解
    • Spring AOP 深度剖析与实践
    • Spring 三级缓存机制深度解析
    • 深入 Spring 源码,剖析设计模式的落地实践
    • 探索 Spring 事务的奥秘
    • 深入解析Spring Bean的生命周期管理
    • 解读 Spring Boot 核心知识点
    • Spring Boot 启动优化实战:1分钟到13秒的排查与优化之路
    • Spring Boot自动装配原理及实践
    • 一文快速上手Sharding-JDBC
    • sharding-jdbc如何实现分页查询
    • 基于DynamicDataSource整合分库分表框架Shardingsphere
  • 计算机组成原理

    • 计算机硬件知识小结
    • CPU核心知识点小结
    • 浅谈CPU流水线的艺术
    • 从Java程序员视角聊聊CPU缓存
    • CPU任务调度和伪共享问题小结
    • CPU MESI缓存一致性协议
    • CPU内存管理机制
    • 内存深度解析
    • 磁盘存储原理
    • 详解计算机启动步骤
    • CPU南北桥架构与发展史
    • CPU中断机制与硬件交互详解
  • 操作系统

    • 如何实现一个高性能服务器
    • Linux文件结构与文件权限
    • Linux常见压缩指令小结
    • Linux核心系统调用详解
    • Linux进程管理
    • Linux线程管理
    • 进程与线程深度解析
    • Linux进程间通信机制
    • 零拷贝技术原理与实践
    • CPU缓存一致性问题深度解析
    • IO任务与CPU调度艺术
  • 计算机网络

    • 网卡通信原理详解
    • 网卡数据包处理指南
    • 基于抓包详解TCP协议
  • 编码最佳实践

    • 浅谈现代软件工程TDD最佳实践
    • 浅谈TDD模式下并发程序设计与实现
    • 面向AI编程新范式Trae后端开发环境搭建与实践
    • 基于提示词工程的Redis签到功能开发实践
    • 基于Vibe Coding的Redis分页查询实现
    • 告别AI无效对话:资深工程师的提示词设计最佳实践
  • 实用技巧与配置

    • Mac常用快捷键与效率插件指南
    • Keynote技术科普短视频制作全攻略
  • 写作

    • 写好技术博客的5大核心原则:从认知科学到AI工具的全流程指南
  • 开发工具

    • IDEA配置详解与高效使用指南
  • Nodejs
  • 博客搭建
  • Redis

    • Redis核心知识小结
    • 解锁Redis发布订阅模式
    • 掌握Redis事务
    • Redis主从复制技术
    • Redis的哨兵模式详解
    • 深度剖析Redisson分布式锁
    • 详解redis单线程设计思路
    • 来聊聊Redis所实现的Reactor模型
    • Redis RDB持久化源码深度解析
    • 来聊聊redis的AOF写入
    • 来聊聊Redis持久化AOF管道通信的设计
    • 来聊聊redis集群数据迁移
    • Redis SDS动态字符串深度解析
    • 高效索引的秘密:redis跳表设计与实现
    • 聊聊redis中的字典设计与实现
  • MySQL

    • MySQL基础知识点小结
    • 解读MySQL 索引基础
    • MySQL 索引进阶指南
    • 解读MySQL Explain关键字
    • 探秘 MySQL 锁:原理与实践
    • 详解MySQL重做日志redolog
    • 详解undoLog在MySQL MVCC中的运用
    • MySQL二进制日志binlog核心知识点
    • MySQL高效插入数据的最佳实践
    • MySQL分页查询优化指南
    • MySQL流式查询的奥秘与应用解析
    • 来聊聊分库分表
    • 来聊聊大厂常用的分布式ID生成方案
  • ElasticSearch

    • 从Lucene到Elasticsearch:进化之路
    • ES 基础使用指南
    • ElasticSearch如何写入一篇文档
    • 深入剖析Elasticsearch文档读取原理
    • 聊聊ElasticSearch性能调优
    • Spring借助Easy-Es操作ES
  • Netty

    • 一文快速了解高性能网络通信框架Netty
    • Netty网络传输简记
    • 来聊聊Netty的ByteBuf
    • 来聊聊Netty消息发送的那些事
    • 解密Netty高性能之谜:NioEventLoop线程池阻塞分析
    • 详解Netty中的责任链Pipeline如何管理ChannelHandler
    • Netty Reactor模型常见知识点小结
    • Netty如何驾驭TCP流式传输?粘包拆包问题全解
    • Netty解码器源码解析
  • 消息队列

    • 一文快速入门消息队列
    • 消息队列RocketMQ入门指南
    • 基于RocketMQ实现分布式事务
    • RocketMQ容器化最佳实践
    • RocketMQ常见问题与深度解析
    • Kafka快速安装与使用指南
  • Nginx

    • Linux下的nginx安装
    • Nginx基础入门总结
    • Nginx核心指令小结
    • Nginx进程结构与核心模块初探
    • Nginx应用进阶HTTP核心模块配置
    • Nginx缓存及HTTPS配置小记
    • nginx高可用实践简记
    • Nginx性能优化
  • 微服务基础

    • 微服务基础知识小结
    • 分布式事务核心概念小结
    • OpenFeign核心知识小结
    • 微服务组件Gateway核心使用小结
    • 分布式事务Seata实践
    • 用 Docker Compose 完成 Seata 的整合部署
  • Nacos

    • Nacos服务注册原理全解析
    • Nacos服务订阅流程全解析
    • Nacos服务变更推送流程全解析
    • 深入解析SpringCloud负载均衡器Loadbalancer
    • Nacos源码环境搭建与调试指南
  • Seata

    • 深度剖析Seata源码
  • Docker部署

    • 一文快速掌握docker的理念和基本使用
    • 使用docker编排容器
    • 基于docker-compose部署微服务基本环境
    • 基于docker容器化部署微服务
    • Gateway全局异常处理及请求响应监控
    • Docker图形化界面工具Portainer最佳实践
  • Go基础

    • 一文带你速通Go语言基础语法
    • 一文快速掌握Go语言切片
    • 来聊聊go语言的hashMap
    • 一文速通go语言类型系统
    • 浅谈Go语言中的面向对象
    • go语言是如何实现协程的
    • 聊聊go语言中的GMP模型
    • 极简的go语言channel入门
    • 聊聊go语言基于epoll的网络并发实现
    • 写给Java开发的Go语言协程实践
  • mini-redis实战

    • 来聊聊我用go手写redis这件事
    • mini-redis如何解析处理客户端请求
    • 实现mini-redis字符串操作
    • 硬核复刻redis底层双向链表核心实现
    • 动手复刻redis之go语言下的字典的设计与落地
    • Go 语言下的 Redis 跳表设计与实现
    • Go 语言版 Redis 有序集合指令复刻探索
  • 项目编排

    • Spring脚手架创建简记
    • Spring脚手架集成分页插件
    • Spring脚手架集成校验框架
    • maven父子模块两种搭建方式简记
    • SpringBoot+Vue3前后端快速整合入门
    • 来聊聊Java项目分层规范
  • 场景设计

    • Java实现文件分片上传
    • 基于时间缓存优化浏览器轮询阻塞问题
    • 基于EasyExcel实现高效导出
    • 10亿数据高效插入MySQL最佳方案
    • 从开源框架中学习那些实用的位运算技巧
  • CI/CD

    • 基于NETAPP实现内网穿透
    • 基于Gitee实现Jenkins自动化部署SpringBoot项目
    • Jenkins离线安装部署教程简记
    • 基于Nexus搭建Maven私服基础入门
    • 基于内网的Jenkins整合gitlab综合方案简记
  • 监控方法论

    • SpringBoot集成Prometheus与Grafana监控
    • Java监控度量Micrometer全解析
    • 从 micrometer计量器角度快速上手promQL
    • 硬核安利一个监控告警开源项目Nightingale
  • Spring AI

    • Spring AI Alibaba深度实战:一文掌握智能体开发全流程
    • Spring AI Alibaba实战:JVM监控诊断Arthas Agent的工程化构建与最佳实践
  • 大模型评测

    • M2.7 真能打!我用两个真实场景测了测,结果有点意外
    • Qoder JetBrains插件评测:祖传代码重构与接口优化实战
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

sharkchili

计算机禅修者
首页
  • Java基础

    • 聊一聊java一些核心知识点
    • 聊聊java面向对象核心知识点
    • 聊聊Java中的异常
    • 聊聊Java中的常用类String
    • 万字长文带你细聊Java注解本质
    • 来聊聊Java的反射机制
    • 深入解析Java泛型的魅力与机制
    • Java集合框架深度解析与面试指南
    • Java常用集合类HashMap深度解析
    • LinkedHashMap源码到面试题的全解析
    • 深入解析CopyOnWriteArrayList的工作机制
    • Java基础IO总结
    • Java三大IO模型小结
    • Java BIO NIO AIO详解
    • Java进阶NIO之IO多路复用详解
    • Java8流式编程入门
    • 一文速通lambda与函数式编程
    • Java8函数式方法引用最佳实践
  • Java并发编程

    • Java并发编程基础小结
    • 深入理解Java中的final关键字
    • 浅谈Java并发安全发布技术
    • 浅谈Java并发编程中断的哲学
    • Java线程池知识点小结
    • 浅谈Java线程池中拒绝策略与流控的艺术
    • synchronized关键字使用指南
    • 深入源码解析synchronized关键字
    • 详解JUC包下的锁
    • 详解并发编程中的CAS原子类
    • LongAdder源码分析
    • AQS源码解析
    • 深入剖析Java并发编程中的死锁问题
    • Java并发容器总结
    • 详解Java并发编程volatile关键字
    • 并发编程ThreadLocal必知必会
    • CompletableFuture基础实践小结
    • CompletableFuture异步多任务最佳实践
    • 硬核详解FutureTask设计与实现
    • 线程池大小设置的底层逻辑与场景化方案
    • 来聊一个有趣的限流器RateLimiter
  • JVM相关

    • 从零开始掌握 JVM
    • JVM核心知识点小结
    • JVM指令集概览:基础与应用
    • JVM类加载器深度解析
    • JVM方法区深度解析
    • Java内存模型JMM详解
    • Java对象大小的精确计算方法
    • 逃逸分析在Java中的应用与优化
    • 从零开始理解JVM的JIT编译机制
    • G1垃圾回收器:原理详解与调优指南
    • JVM故障排查实战指南
    • JVM内存问题排错最佳实践
    • JVM内存溢出排查指南
    • 简明的Arthas使用教程
    • 简明的Arthas配置及基础运维教程
    • 基于Arthas Idea的JVM故障排查与指令生成
    • 基于arthas量化监控诊断java应用方法论与实践
    • 深入剖析arthas技术原理
  • 深入理解Spring框架

    • Spring 核心知识点全面解析
    • Spring核心功能IOC详解
    • Spring AOP 深度剖析与实践
    • Spring 三级缓存机制深度解析
    • 深入 Spring 源码,剖析设计模式的落地实践
    • 探索 Spring 事务的奥秘
    • 深入解析Spring Bean的生命周期管理
    • 解读 Spring Boot 核心知识点
    • Spring Boot 启动优化实战:1分钟到13秒的排查与优化之路
    • Spring Boot自动装配原理及实践
    • 一文快速上手Sharding-JDBC
    • sharding-jdbc如何实现分页查询
    • 基于DynamicDataSource整合分库分表框架Shardingsphere
  • 计算机组成原理

    • 计算机硬件知识小结
    • CPU核心知识点小结
    • 浅谈CPU流水线的艺术
    • 从Java程序员视角聊聊CPU缓存
    • CPU任务调度和伪共享问题小结
    • CPU MESI缓存一致性协议
    • CPU内存管理机制
    • 内存深度解析
    • 磁盘存储原理
    • 详解计算机启动步骤
    • CPU南北桥架构与发展史
    • CPU中断机制与硬件交互详解
  • 操作系统

    • 如何实现一个高性能服务器
    • Linux文件结构与文件权限
    • Linux常见压缩指令小结
    • Linux核心系统调用详解
    • Linux进程管理
    • Linux线程管理
    • 进程与线程深度解析
    • Linux进程间通信机制
    • 零拷贝技术原理与实践
    • CPU缓存一致性问题深度解析
    • IO任务与CPU调度艺术
  • 计算机网络

    • 网卡通信原理详解
    • 网卡数据包处理指南
    • 基于抓包详解TCP协议
  • 编码最佳实践

    • 浅谈现代软件工程TDD最佳实践
    • 浅谈TDD模式下并发程序设计与实现
    • 面向AI编程新范式Trae后端开发环境搭建与实践
    • 基于提示词工程的Redis签到功能开发实践
    • 基于Vibe Coding的Redis分页查询实现
    • 告别AI无效对话:资深工程师的提示词设计最佳实践
  • 实用技巧与配置

    • Mac常用快捷键与效率插件指南
    • Keynote技术科普短视频制作全攻略
  • 写作

    • 写好技术博客的5大核心原则:从认知科学到AI工具的全流程指南
  • 开发工具

    • IDEA配置详解与高效使用指南
  • Nodejs
  • 博客搭建
  • Redis

    • Redis核心知识小结
    • 解锁Redis发布订阅模式
    • 掌握Redis事务
    • Redis主从复制技术
    • Redis的哨兵模式详解
    • 深度剖析Redisson分布式锁
    • 详解redis单线程设计思路
    • 来聊聊Redis所实现的Reactor模型
    • Redis RDB持久化源码深度解析
    • 来聊聊redis的AOF写入
    • 来聊聊Redis持久化AOF管道通信的设计
    • 来聊聊redis集群数据迁移
    • Redis SDS动态字符串深度解析
    • 高效索引的秘密:redis跳表设计与实现
    • 聊聊redis中的字典设计与实现
  • MySQL

    • MySQL基础知识点小结
    • 解读MySQL 索引基础
    • MySQL 索引进阶指南
    • 解读MySQL Explain关键字
    • 探秘 MySQL 锁:原理与实践
    • 详解MySQL重做日志redolog
    • 详解undoLog在MySQL MVCC中的运用
    • MySQL二进制日志binlog核心知识点
    • MySQL高效插入数据的最佳实践
    • MySQL分页查询优化指南
    • MySQL流式查询的奥秘与应用解析
    • 来聊聊分库分表
    • 来聊聊大厂常用的分布式ID生成方案
  • ElasticSearch

    • 从Lucene到Elasticsearch:进化之路
    • ES 基础使用指南
    • ElasticSearch如何写入一篇文档
    • 深入剖析Elasticsearch文档读取原理
    • 聊聊ElasticSearch性能调优
    • Spring借助Easy-Es操作ES
  • Netty

    • 一文快速了解高性能网络通信框架Netty
    • Netty网络传输简记
    • 来聊聊Netty的ByteBuf
    • 来聊聊Netty消息发送的那些事
    • 解密Netty高性能之谜:NioEventLoop线程池阻塞分析
    • 详解Netty中的责任链Pipeline如何管理ChannelHandler
    • Netty Reactor模型常见知识点小结
    • Netty如何驾驭TCP流式传输?粘包拆包问题全解
    • Netty解码器源码解析
  • 消息队列

    • 一文快速入门消息队列
    • 消息队列RocketMQ入门指南
    • 基于RocketMQ实现分布式事务
    • RocketMQ容器化最佳实践
    • RocketMQ常见问题与深度解析
    • Kafka快速安装与使用指南
  • Nginx

    • Linux下的nginx安装
    • Nginx基础入门总结
    • Nginx核心指令小结
    • Nginx进程结构与核心模块初探
    • Nginx应用进阶HTTP核心模块配置
    • Nginx缓存及HTTPS配置小记
    • nginx高可用实践简记
    • Nginx性能优化
  • 微服务基础

    • 微服务基础知识小结
    • 分布式事务核心概念小结
    • OpenFeign核心知识小结
    • 微服务组件Gateway核心使用小结
    • 分布式事务Seata实践
    • 用 Docker Compose 完成 Seata 的整合部署
  • Nacos

    • Nacos服务注册原理全解析
    • Nacos服务订阅流程全解析
    • Nacos服务变更推送流程全解析
    • 深入解析SpringCloud负载均衡器Loadbalancer
    • Nacos源码环境搭建与调试指南
  • Seata

    • 深度剖析Seata源码
  • Docker部署

    • 一文快速掌握docker的理念和基本使用
    • 使用docker编排容器
    • 基于docker-compose部署微服务基本环境
    • 基于docker容器化部署微服务
    • Gateway全局异常处理及请求响应监控
    • Docker图形化界面工具Portainer最佳实践
  • Go基础

    • 一文带你速通Go语言基础语法
    • 一文快速掌握Go语言切片
    • 来聊聊go语言的hashMap
    • 一文速通go语言类型系统
    • 浅谈Go语言中的面向对象
    • go语言是如何实现协程的
    • 聊聊go语言中的GMP模型
    • 极简的go语言channel入门
    • 聊聊go语言基于epoll的网络并发实现
    • 写给Java开发的Go语言协程实践
  • mini-redis实战

    • 来聊聊我用go手写redis这件事
    • mini-redis如何解析处理客户端请求
    • 实现mini-redis字符串操作
    • 硬核复刻redis底层双向链表核心实现
    • 动手复刻redis之go语言下的字典的设计与落地
    • Go 语言下的 Redis 跳表设计与实现
    • Go 语言版 Redis 有序集合指令复刻探索
  • 项目编排

    • Spring脚手架创建简记
    • Spring脚手架集成分页插件
    • Spring脚手架集成校验框架
    • maven父子模块两种搭建方式简记
    • SpringBoot+Vue3前后端快速整合入门
    • 来聊聊Java项目分层规范
  • 场景设计

    • Java实现文件分片上传
    • 基于时间缓存优化浏览器轮询阻塞问题
    • 基于EasyExcel实现高效导出
    • 10亿数据高效插入MySQL最佳方案
    • 从开源框架中学习那些实用的位运算技巧
  • CI/CD

    • 基于NETAPP实现内网穿透
    • 基于Gitee实现Jenkins自动化部署SpringBoot项目
    • Jenkins离线安装部署教程简记
    • 基于Nexus搭建Maven私服基础入门
    • 基于内网的Jenkins整合gitlab综合方案简记
  • 监控方法论

    • SpringBoot集成Prometheus与Grafana监控
    • Java监控度量Micrometer全解析
    • 从 micrometer计量器角度快速上手promQL
    • 硬核安利一个监控告警开源项目Nightingale
  • Spring AI

    • Spring AI Alibaba深度实战:一文掌握智能体开发全流程
    • Spring AI Alibaba实战:JVM监控诊断Arthas Agent的工程化构建与最佳实践
  • 大模型评测

    • M2.7 真能打!我用两个真实场景测了测,结果有点意外
    • Qoder JetBrains插件评测:祖传代码重构与接口优化实战
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 计算机组成原理

    • 计算机硬件知识小结
    • 编程语言是如何完成运算的
    • CPU核心知识点小结
    • 浅谈CPU流水线的艺术
    • 从Java程序员视角聊聊CPU缓存
    • CPU任务调度和伪共享问题小结
    • CPU如何完成计算运算
    • CPU指令封装原理
    • CPU性能优化技术详解
    • CPU MESI缓存一致性协议
    • CPU内存管理机制
    • 内存深度解析
    • 磁盘存储原理
      • 引言
      • 详解磁盘基本构造和工作原理
        • 磁盘的基本构造
        • 操作系统下磁盘数据读写的工作流程
      • 磁盘管理的哲学
        • 操作系统对于数据单位的抽象
        • 如何进行数据块信息的管理
        • 大文件空间管理
        • 文件索引
        • 操作系统下不同分区管理的哲学
      • 现代存储设备的发展
        • 固态硬盘(SSD)
        • 日志结构文件系统
      • 小结
      • 参考
    • GPU工作原理简析
    • 详解计算机启动步骤
    • CPU南北桥架构与发展史
    • CPU中断机制与硬件交互详解
  • 操作系统

  • 计算机网络

  • 运维

  • 编码最佳实践

  • 计算机基础
  • 计算机组成原理
sharkchili
2026-03-25
目录

磁盘存储原理

[toc]

# 引言

# 详解磁盘基本构造和工作原理

# 磁盘的基本构造

磁盘的大部分空间都是磁性材料,这些材料可以被磁化为两个不同的方向,一个方向代表1,另一个方向代表0,多个磁性单元组成一个单元用于表示1bit,也正是通过这样无数个磁性单元构成一张可以存储大量数据的磁盘:

然后就是机械硬盘的另一个组成部分——磁头,当需要进行数据读写时,磁盘就会转动将目标数据对应的位置定格在磁头上(常见转速为每分钟5400转或7200转),同时为避免磁头刮坏磁盘,二者的距离设置非常小。

而磁头是由读写磁头两个部分构成,针对读时,读磁头就会通过电磁技术感知磁盘磁性单元的极性确定数值是0还是1,同理针对写时,即通过写磁针修改磁性单元的极性完成二进制数值0或1的修改。

最后一个核心的部分也就是扇区,磁盘是由多个圆盘堆叠构成,每个圆盘又有无数个同心圆也就是磁道,每个磁道进行切割划分构成了扇区,传统扇区大小为512字节,现代硬盘多采用4096字节(4K)扇区。但针对外部磁道扇区密度不均衡的问题就导致了外圈扇区数据稀疏从而导致资源利用率不高,所以后续的优化就将外圈的扇区数均等切割成更多的扇区保证这些空间数据发布密集均匀:

# 操作系统下磁盘数据读写的工作流程

有了上述几个核心部分的了解,我们不妨串联一下这些概念梳理出磁盘的读写过程,假设我们现在要进行数据读,对应的步骤为:

  1. 驱动程序基于数据定制定位到盘面、磁道号、扇区编号

  2. 磁头移动定位到对应的磁道上,这个过程也叫寻道

  3. 磁盘转动定位到对应的扇区

  4. 完成数据读取

# 磁盘管理的哲学

# 操作系统对于数据单位的抽象

磁盘读取基本单位为扇区,传统大小为512字节,现代硬盘多为4096字节。而操作系统的计量单位则是块(block),通常为4KB大小,所以为什么说我们即使读取1字节的文件也要使用4KB的磁盘空间。这一点,我们可以通过stat -f命令查看:


sharkchili@DESKTOP-0F6E7K1:~$    stat -f /


# 查看文件系统信息
# File: "/"                    # 检查的文件系统挂载点
# ID: 1bce3e168ac7b648        # 文件系统标识符
# Namelen: 255                # 文件名最大长度
# Type: ext2/ext3             # 文件系统类型
# Block size: 4096            # 文件系统块大小为4096字节(4KB)
# Fundamental block size: 4096 # 基本块大小为4096字节(4KB)
# Blocks: Total: 263940717    # 总块数: 263,940,717个
# Free: 262373060             # 空闲块数: 262,373,060个
# Available: 248947192        # 可用块数: 248,947,192个
# Inodes: Total: 67108864     # 总Inode数: 67,108,864个
# Free: 67040061              # 空闲Inode数: 67,040,061个


  File: "/"
    ID: 1bce3e168ac7b648 Namelen: 255     Type: ext2/ext3
Block size: 4096       Fundamental block size: 4096
Blocks: Total: 263940717  Free: 262373060  Available: 248947192
Inodes: Total: 67108864   Free: 67040061
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 如何进行数据块信息的管理

上述4KB构成一个块,为了记录块的使用情况,操作系统在磁盘特定位置专门使用一块空间记录块的使用情况也就是我们常说的位图索引,1bit代表一个块,0表示空闲,1表示已使用,一般情况下这个块位图位于文件系统的特定区域:

#

但是硬盘空间非常庞大,所以定位某个单位块若采用扫描这种方式是非常低效的,所以我们就需要记录对应数据的元信息,于是就考虑使用一个名为inode的数据结构记录文件的物理元信息,而每个inode大小因文件系统而异,常见大小为128或256字节,存储的元信息包含:

  1. 数据占用物理空间
  2. 块起始号
  3. 数据块数量
  4. 权限
  5. 时间

我们可以通过Linux的stat指令查看inode文件的详情,例如我们在tmp文件夹下有一个file文件,内部包含数据hello world,我们就可以执行stat指令查看,此时我们就可以看到:

  1. 文件大小12字节
  2. 占用8个磁盘块
  3. inode起始编号为6744
  4. 访问权限0664
  5. 修改时间、创建时间等信息
sharkchili@DESKTOP-0F6E7K1:/tmp$ stat  file 
  File: file
  Size: 12              Blocks: 8          IO Block: 4096   regular file
Device: 8,48    Inode: 6744        Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/sharkchili)   Gid: ( 1000/sharkchili)
Access: 2025-09-13 17:07:21.291934846 +0800
Modify: 2025-09-13 17:08:12.992226483 +0800
Change: 2025-09-13 17:08:12.992226483 +0800
 Birth: 2025-09-13 17:07:21.291934846 +0800
1
2
3
4
5
6
7
8
9

由此无数个文件就基于这些inode构成一张inode表,同时考虑到inode块定位的效率,在块位图之后又补充了一个inode块位图,同时也将inode表追加在inode块位图后面:

# 大文件空间管理

通过上述一系列数据结构我们可以很好管理磁盘空间并保证读写效率,但由此也衍生了两个问题:

  1. 磁盘空间分配
  2. 大文件元信息存储

我们先来说说问题1,针对文件的磁盘空间分配整体方向就是两个,连续分配和非连续分配,前者对于文件数据读取友好但是存在磁盘碎片问题,试想这样一种情况,经过连续分配我们的磁盘空间存在两个非连续的磁盘块,此时我们需要存储一个文件大小为4097字节的文件,因为磁盘块每个大小都是4096字节,按照连续分配法,我们就必须要有一个连续两个磁盘块的磁盘空间,所以这种文件分配策略下,文件就无法存储到磁盘,这两个非连续的空闲空间就无法被使用,变成空洞块,导致磁盘碎片:

所以设计者们为了最大化利用磁盘空间,采用非连续分配,由此就有了问题2的探讨——如何维护大文件信息。大文件元信息维护,要知道现在的大文件动不动就是几个G,所以一个inode只有128或256字节,如果直接记录磁盘块信息,最多只能记录少量磁盘块,无法完整维护一份大文件的元信息,所以inode在原有基础上抽象出指针指向全新的数据块,即通过间接索引指向的空间继续存储其他磁盘块的信息以保证记录大文件:

# 文件索引

自此我们解决了文件存储和文件元信息维护问题,接下来我们再说说文件的索引,对于文件的定位从使用者的角度来看,自然是希望基于文件名的方式定位而非inode号,所以我们针对文件名和inode(如果是大文件就和第一个inode建立映射)建立映射,于是我们就有了一张记录文件名和对应inode映射,这就是操作系统中目录的概念:

基于这个思路我们再继续分析,要知道操作系统中的文件可能有数亿个,所以为了提升检索效率,我们打算将目录分层,即根目录下挂着目录项或者又一个子目录,如此一级一级层次下推构成一个树结构的目录,通过根目录我们就可以定位到对应的文件名的inode:

最后再把这个根目录对应的文件维护到inode表的开头位置,后续就可以顺着这个目录进行文件映射inode读写操作了。

# 操作系统下不同分区管理的哲学

最后一个问题,如何构建一张检索高效且可以记录整个磁盘数据对应inode信息的inode表,之所以这么问,是因为一个磁盘块4KB,而一个inode项大小为128或256字节,对应4096/128=32或4096/256=16这意味着单个块只能维护16或32个inode。所以我们就需要多个块才能构建出一个大的inode表。于是我们在原有基础上添加一个块专门记录inode表使用的数据块,这就是我们常说的inode表块指针:

基于这个问题,我们也联想到块位图,一个块位图对应4KB,假设1个bit代表一个磁盘块,对应4096*8也就是32768个磁盘块,对应128M,这很明显也不够的。于是文件系统就考虑到将磁盘空间的块进行划分,把一组相关的块当作一个块组,这些块组交由组描述符进行统一管理,如下图,多个块构成块组,包括块位图、inode块位图、inode表等,原本描述全局的inode表项的描述符变为组描述符统一管理这个块组。

与之对应操作系统若想知道块组的使用情况,于是在第一个块组中添加一个超级块记录整个文件系统的元信息,而其他块组则是拷贝这份信息作为冗余:

最后操作系统存在多分区,所以:

  1. 每个分区对应多个块组

  2. 每个分区对应一个启动扇区(boot sector),作为安装操作系统时写入引导程序的位置

汇总上述信息,以操作系统分区3为例,对应的逻辑结构如下,即一个分区对应引导块和块组,每个块组由组描述符统一维护各种元信息:

最后为了维护各个分区的元信息,在硬盘的第一个扇区作为MBR(Master Boot Record),引导系统启动加载和管理这些分区。

# 现代存储设备的发展

# 固态硬盘(SSD)

随着技术的发展,固态硬盘(SSD)逐渐成为主流存储设备之一。与传统机械硬盘(HDD)不同,SSD使用闪存芯片存储数据,具有以下特点:

  1. 无机械运动部件,读写速度快
  2. 功耗低,噪音小
  3. 随机访问性能优异
  4. 但存在写入寿命限制和写入放大问题

# 日志结构文件系统

现代文件系统如日志文件系统(Journaling File System)通过引入日志机制来提高文件系统的可靠性,当系统崩溃时可以通过日志恢复数据一致性。

# 小结

最后我们再来自底向上的总结一下本文知识点:

  1. 磁盘通过磁性材料维护数据、通过磁头寻址读写,磁盘由多个圆盘构成,每个圆盘对应磁道,磁道划分为扇区进行管理,传统扇区大小为512字节,现代硬盘多为4096字节
  2. 操作系统以磁盘块为单位管理磁盘扇区,每个磁盘块通常为4096字节
  3. 操作系统通过块位图统一管理磁盘块空闲空间
  4. 每个文件可能用到多个磁盘块,所以通过inode信息维护文件使用的磁盘块和元信息
  5. 操作系统通过inode表统一管理维护inode信息
  6. 为方便用户检索文件,通过目录维护文件名和inode映射,同时为了管理更多的文件,引出目录和子目录的层次结构
  7. 为方便统一管理磁盘空间,将磁盘块分为多个块组独立管理,这样就缩小了inode、块位图、inode位图的管辖范围
  8. 操作系统分为多分区,所以每个分区划分几个块组,并添加一个引导扇区作为操作系统安装引导程序的数据块
  9. 操作系统通过MBR作为引导块统一管理多分区
  10. 现代存储技术如SSD和日志文件系统进一步提升了存储性能和可靠性

# 参考

《趣话计算机底层技术》

Linux的i节点(inode) 和 数据块(Block)相关操作详解:https://blog.csdn.net/lianghudream/article/details/150543987 (opens new window)

编辑 (opens new window)
上次更新: 2026/03/26, 01:05:31
内存深度解析
GPU工作原理简析

← 内存深度解析 GPU工作原理简析→

最近更新
01
基于EasyExcel实现高效导出
03-25
02
从开源框架中学习那些实用的位运算技巧
03-25
03
浅谈分布式架构设计思想和常见优化手段
03-25
更多文章>
Theme by Vdoing | Copyright © 2025-2026 Evan Xu | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×
×