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

【 linux 】文件系统

目录

1. 聊一聊硬件

2. 文件系统

2.1 结构

2.2 路径解析

2.3 挂载分区

2.4 总结


1. 聊一聊硬件

想知道文件是如何管理的和硬件是分不开的,这里看一下硬件磁盘的组成和原理

磁盘存储的基本单位是扇区,一个扇区通常能存储512字节,除了扇区一个磁盘还有磁道,柱面,传动臂等结构

柱面,磁头,扇区三者组成了CHS定址

OS文件系统访问磁盘,不以扇区为单位,而是以“”为单位,一般是4KB,连续8个扇区,“块”是文件存取的最小单位

为了便于管理,OS对磁盘进行了分区分组。这样对一组的管理就是对磁盘的管理

文件=内容+属性,linux下,内容和属性是分开存储的,内容存储在Data Blocks区,属性存储在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...

文件名属性并未纳入inode数据结构中,任何文件的内容大小可以不同,但是属性大小是相同的

认识了硬盘这种“块”设备,块是分区下的结构,如何找到块,又如何管理这些inode就是文件系统的工作

2. 文件系统

2.1 结构

文件系统的目的是组织和管理硬盘中的文件,文件系统将整个分区划分成若干个大小的块组,只要能管理一个分区,就能管理所有分区,就能管理所有磁盘文件

依次介绍一下各部分的作用

1. Super Block

存放⽂件系统本⾝的结构信息,描述整个分区的⽂件系统信息。记录的信息主要有:bolck和inode的总量,未使⽤的block和inode的数量,⼀个block和inode的⼤⼩,最近⼀次挂载的时间,最近⼀次写⼊数据的时间,最近⼀次检验磁盘的时间等其他⽂件系统的相关信息

2. GDT

块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描述符存储⼀个块组的描述信息,如在这个块组中从哪⾥开始是inodeTable,从哪⾥开始是Data Blocks,空闲的inode和数据块还有多少个等等。块组描述符在每个块组的开头都有⼀份拷⻉

3. Block Bitmap

记录着Data Blocks中哪个数据块已被占用,哪个数据块还没有被占用

4. Inode Bitmap

每个bit表示一个inode是否空闲可用

5. Inode Table

存放文件属性,当前分组所有indoe属性的集合,inode编号以分区为单位,不可跨分区

6. Data Block

数据区:存放文件内容,也就是一个个的block,根据不同的文件类型情况不同。对于普通⽂件,⽂件的数据存储在数据块中。对于⽬录,该⽬录下的所有文件名和目录名存储在所在⽬录的数据块中,除了⽂件名外,ls-l命令 看到的其它信息保存在该⽂件的inode中,Block号按照分区划分,不可跨分区

创建一个文件的过程

目录也是文件,属性不用多说,内容保存的是文件名和inode的映射关系

Filename: mnt, Inode: 1048577 Filename: tmp, Inode: 1179650 Filename: sys, Inode: 917506 Filename: libx32, Inode: 17 Filename: srv, Inode: 786434 Filename: lib64, Inode: 16 Filename: sbin, Inode: 18 Filename: dev, Inode: 131073 Filename: swapfile, Inode: 12 Filename: run, Inode: 104857

所以,访问文件,必须打开当前目录,获得对应的inode号,然后进行文件访问

2.2 路径解析

要想访问当前文件需要知道当前文件的目录,目录也是文件,所以也需要知道上一级目录,如此递归下去,出口就是根目录。从根目录开始依次访问每个目录下指定的目录,直到访问到文件,这个过程叫linux路径解析

如果访问任何文件,都从/目录开始进行路径解析太慢了,所以linux会缓存历史路径结构,Linux中,在内核中维护树状路径结构的内核结构体叫做:struct dentry

struct dentry { struct inode *d_inode; /* Where the name belongs to - NULL is negative */ struct dentry *d_parent; /* parent directory */ struct list_head d_lru; /* LRU list */ struct list_head d_subdirs; /* our children */ struct super_block *d_sb; /* The root of the dentry tree */ ... }

每个文件都有对应的dentry结构,包括普通文件。这样所有被打开的文件,就可以在内存中形成整个树形结构。dentry是纯内存结构,磁盘上不存在dentry,磁盘上只有目录文件的数据块,内核读取后转化成内存中的dentry

2.3 挂载分区

挂载分区是为了解决跨分区问题,

挂载 = 把分区的根目录"嫁接"到现有目录树的某个节点上

挂载前: 挂载后 (mount /dev/sdb1 /mnt/data): / / ├── home ├── home ├── etc ├── etc └── mnt └── mnt └── data ← (空目录) └── data ← 现在指向 /dev/sdb1 的根目录 ├── photos/ ├── videos/ └── backup.tar.gz

挂载的本质是在 VFS 层创建一个特殊的 dentry,其 d_flags 标记为 DCACHE_MOUNTED,并将该 dentry 的 d_inode 指向新分区的根 inode,路径解析时,内核遇到带 DCACHE_MOUNTED 标志的 dentry,会自动跳转到对应文件系统的根 dentry 继续解析

2.4 总结

进程pcb中有两个指针*fs和*files,*fs指向fs_struct,存储的是该进程当前的文件系统上下文信息,它保存了进程的根目录、当前工作目录和 umask,本质上是该进程在 VFS 目录树中的"导航状态"

注意的是fs_struct存储的是路径解析的起点(锚点),而不是路径解析过程中产生的 dentry 链或缓存结构。只存储两个特定的 dentry 引用(root 和 pwd)作为解析基准,是进程级别的上下文配置,告诉 VFS "从哪里开始解析"。解析过程中经过的所有中间 dentry,都存在于全局的 dentry cache (dcache)中,不属于任何进程的fs_struct

struct file中确实包含struct path,而struct path内部又包含了dentry防止路径发生变化或者相对路径缺失。struct file中的path打开后是永不改变的

串联一下

open("config.txt") │ ▼ 1. VFS 从 current->fs->pwd.dentry 出发 ← fs_struct 提供起点 │ ▼ 2. 在全局 dcache 中逐级查找 "config.txt" ← dcache 提供缓存 │ ▼ 3. 找到目标 dentry + inode │ ▼ 4. 分配 struct file,将结果存入 f_path + f_inode ← file 记住结果 │ ▼ 5. 返回 fd,存入 current->files->fd[n] ← files_struct 管理描述符 │ ▼ 6. 后续 read(fd) 直接使用 file->f_path/f_inode ← 不再碰 fs_struct

最后一张图加深记忆


http://www.jsqmd.com/news/907419/

相关文章:

  • Solar Pro Preview 模型架构详解:从Phi-3-medium到220亿参数的深度上采样技术
  • NLP —— 英译法实例
  • IPv4 和 IPv6 在地址结构、表示方式、地址空间大小及计算逻辑上存在根本性差异
  • 告别ifconfig!用networkctl命令优雅管理你的Linux网络(systemd-networkd实战)
  • Keil MDK许可证问题解析与解决方案
  • 第3章:裂痕——Siri、Copilot与寄生者入侵
  • 10.【学习】SPI UART 验证环境与测试用例
  • GeoServer数据源创建失败?别慌,可能是这个Windows文件命名‘潜规则’在捣鬼
  • 如何安全备份微信聊天记录:完整指南与实用工具推荐
  • WPF文本框的Placeholder效果,除了Watermark和Style,这几种实现方式你知道吗?
  • 别再踩坑了!手把手教你用YOLOv5 v6.0 + ONNX在Ubuntu 20.04的ROS上部署目标检测(附VMware虚拟机USB摄像头连接完整流程)
  • Python爬虫实战:极客实战 - 全自动化构建 GraphQL/REST API 结构化字典!
  • 别再折腾Docker了!Ubuntu 22.04上源码编译ZLMediaKit保姆级教程(含libsrtp/openssl避坑指南)
  • Midjourney Remix mode保姆级教程:手把手教你修改提示词,让AI更懂你
  • 脉冲神经网络与二进制权重的能效优化技术
  • UE4半透明材质性能优化全指南:从Surface模式选择到RTGI参数调优
  • 千问大模型在阿里生态中的核心应用场景与落地价值
  • 告别‘一大片爆红’:手把手教你用CMake-GUI无错配置VTK(Windows/VS2022版)
  • 避坑指南:DataSophon部署中那些官方文档没细说的坑(防火墙、MySQL、Nginx配置)
  • 模型迁移的“翻译官”——AMCT异构计算管理实战与自定义算子解决方案
  • 形式化验证赋能可解释AI:ViTaX框架如何保证解释的鲁棒性与必要性
  • 【评测】CSDN大模型热点洞察创作流程与评测
  • QiLink 项目的发起人徐玉生孤岛筑塔与温柔渗透
  • [智能体-106]:在相同的输入的情况下,每次调用,大模型具有相同的输出或具有不同的输出的原理?
  • 别再自己造轮子了!盘点那些能直接提升UniApp开发效率的34个原生插件
  • Vue+Element UI项目里,Table数据刷新后展开状态丢失?教你用expand-row-keys动态恢复
  • 【OpenClaw篇】OpenClaw 实战入门:在 VMware 虚拟机里部署第一个本地 AI Agent
  • BarTender 2022 Print Portal安装踩坑实录:从‘无法访问localhost’到成功部署的完整排错
  • 如何3分钟搞定QQ空间数据备份:GetQzonehistory终极指南 [特殊字符]
  • PCA降维后数据还能‘还原’吗?用Python实战带你理解信息损失与重构误差(附避坑指南)