文件系统是操作系统用于明确存储设备或分区上的文件的方法 和数据结构 ; 即在存储设备上组织文件的方法。操作系统中负 责管理和存储文件信息的软件结构称为文件管理系统 , 简称文件系统。 简单来说 , 它负责三件事
把存储设备上的"块" → 组织成"文件和目录" → 提供统一的读写/管理接口从系统角度来看 , 文件系统是对文件存储设备的空间进行组织 和分配 , 负责文件存储并对存入的文件进行保护和检索的系统 。具体地说 , 它负责为用户建立文件 , 存入、读出、修改、转 储文件 , 控制文件的存取 , 安全控制 , 日志 , 压缩 , 加密等。
查看当前系统支持的文件系统
cat /proc/filesystems
# 或查看内核模块目录
ls /lib/modules/$(uname -r)/kernel/fs文件系统类型
Linux文件系统 :ext2(Extended file system),ext3,ext4,xfs(SGI),btrfs(Oracle),reiserfs,jfs(AIX),swap光盘:
iso9660Windows:FAT32,exFAT,NTFSUnix:FFS(fast),UFS(unix),JFS2网络文件系统 :
NFS,CIFS集群文件系统 :
GFS2,OCFS2(oracle)分布式文件系统 :
fastdfs,ceph,moosefs,mogilefs,glusterfs,LustreRAW: 未经处理或者未经格式化产生的文件系统
1. 目录层次结构(FHS 标准)
与 Windows 的"多根"结构(C:、D:、E: 盘)不同 , Linux 采用单根树形结构 , 所有文件和目录都从根目录 / 开始 , 硬盘分区、U 盘等都必须挂载到树上的某个挂载点才能访问
/
├── bin 基础用户命令 ( ls、cp、cat、mv ) , 所有用户可用
├── sbin 系统管理命令 ( fdisk、fsck、shutdown、mkfs ) , 需 root
├── boot 内核映像与引导程序 ( vmlinuz、initramfs、GRUB )
├── dev 设备文件 ( /dev/sda 硬盘、/dev/null 黑洞设备 )
├── etc 系统配置文件 ( fstab、passwd、hostname )
├── home 普通用户家目录 ( /home/username )
├── root root 用户家目录 ( 位于根下 , 单用户模式也可访问 )
├── lib 共享库与内核模块 ( 现代系统常软链到 /usr/lib )
├── media 可移动设备自动挂载点 ( U 盘、光盘 )
├── mnt 临时手动挂载点
├── opt 第三方独立软件 ( /opt/google/chrome )
├── proc 虚拟文件系统 : 内核与进程运行时信息 ( /proc/cpuinfo )
├── sys 虚拟文件系统 : 设备与内核配置视图
├── run 运行时数据 ( PID、socket ) , tmpfs , 重启清空
├── tmp 临时文件 , 重启清空
├── usr 用户程序与数据 ( Unix System Resources )
├── var 可变数据 ( 日志 /var/log、缓存、数据库 )
└── lost+found fsck 修复找回的文件存放处FHS 标准的分类思想——按"可共享性"和"是否可变"划分
根目录磁盘空间绝对不可耗尽 , 否则系统无法启动、无法创建新文件、服务崩溃
2. 一切皆文件
在 Linux 中 , 普通文本、目录、设备、进程、网络套接字都以"文件"的方式统一管理
ls -l 第一列标识文件类型
- 普通文件
d 目录
l 符号链接 ( 软链接 )
b 块设备 ( 硬盘 , /dev/sda )
c 字符设备 ( /dev/tty、/dev/null )
p 命名管道
s 套接字块设备 : 按块随机读写(硬盘、SSD)
字符设备 : 按字节流读写(键盘、串口)
3. inode : 文件的"身份证"
3.1. inode基础
inode(Index Node , 索引节点 ) 是文件的唯一标识 , 记录文件的元数据。
文件类型(普通文件、目录、链接等)
权限(
rwx)、所有者(UID/GID)大小、时间戳(
atime、mtime、ctime)链接计数
指向数据块的指针(
ext4中为小文件做了内联优化 , 可把很小的文件直接放进inode)
ls -i filename # 查看 inode 号
stat filename # 查看详细 inode 信息关键: 文件名不存储在
inode中! 文件名与inode的映射关系由目录项(dentry)维护
inode 面试题
1. 一个100M的磁盘分区 , 写入1K的文件或写入1M的文件 , 分别可以写入多少个?
分析 : 换算单位100M=1024000K , 1M=1024K 一个block=4K
如果写入1K的文件 , 由于1K的文件远小于1个block的大小 , 1个block就可以存一个1K的文件 , 所以1024000/4=25600 个文件.
如果写入1M的文件 , 优于1M的文件远大于1个block的大小 , 1个block存不下一个1M的文件 ,
因此 , 1M的文件需要1024/4=256个block块来存1M的文件 , 所以100M的空间最多能存1024000/256=400个文件.
2. 假设你的Ext4文件系统使用 4K block , 而该文件系统中有 10000 个小文件 , 每个文件大小均为 50bytes , 请问此时你的磁盘浪费多少容量?
分析 : 单位换算 , 一个block大小为 4K=4096 bytes 远大于一个文件的大小50bytes
因此一个block就浪费了 4096-50=4046 , 10000个文件就浪费10000*4046=40460000bytes
换算单位 : 浪费了38M左右的容量3.2 dentry / inode / 数据块的关系
文件名(dentry) ──► inode号 ──► inode ( 元数据+块指针 ) ──► 数据块(block)文件名 : 保存在磁盘目录项中
dentry:VFS在内存中维护的路径组件和查找缓存inode:代表文件系统对象 , 保存元数据与数据映射
4. block : 存放数据的地方
4.1 block基础
block 是存放文件内容数据的地方 ,
ext系列支持1K/2K/4K三种 , 格式化后不可更改文件太大 → 占用多个
block; 文件小于block→ 剩余容量浪费
磁盘布局(以 ext 系列为例)
[ 超级块 superblock ] [ inode 区 ] [ 数据块区 ] [ 块位图/inode位图 ]超级块 : 记录文件系统整体信息——块大小、inode 数、空闲块数、挂载状态 , 通常有多个备份副本 ( 块偏移 8193、16385、24577… )
inode 区 : 保存
inode数据块区 : 保存文件实际内容
位图 : 标记哪些块/
inode已使用
inode与block的关系
inode:记录文件的属性 , 一个文件占用一个
inode, 同时记录此文件的数据所在的block号码 ; 由于实际中inode号与文件名分开存储 。block: 是用来放置文件内容数据地地方 , 若文件太大时 , 会占用多个block。在Ext2+文件系统中所支持的block大小有1K,2K及4K三种而已。在格式化时block的大小就固定了 , 且每个block都有编号 , 以方便inode的记录。block有一下注意点。block的大小与数量在格式化完就不能够再改变了(除非重新格式化) ;每个
block内最多只能够放置一个文件的数据 ;如果文件大于
block的大小 , 则一个文件会占用多个block数量 ;如果文件小于
block, 则该block的剩余容量就不能够再被使用了(磁盘空间会浪费)
注:
block越大 ,inode越少 , 适合存储大文件的文件系统 ;block越小 ,inode越多 , 适合存储文件多而小的文件系统。 系统运行时 ,inode和block会在修改后内存与磁盘做一个同步 , 我们用ls -li列出来的内容这是内存中的暂存 , 所以有时候系统非正常的关机会导致block和inode的不同步问题。
4.2 超级块(superblock)
超级块是文件系统特性的记录 , 包括其大小 , 块大小 , 空块和填充块及其各自的计数 , inode表的大小和位置 , 磁盘块映射和使用信息 , 以及 块组的大小。
一个EXT2文件系统时 , 基本的Linux文件系统的类型 , 分为块组 , 其中每个都包含 , 默认情况下 , 8192个块。同一文件系统上的默认块大小为4096 字节。因此 , 在块偏移8193,16385,24577等处存在超级块的备份副本。
可以通过dumpe2fs 查看对应的文件系统超级块信息。 centos6超级块组中有 8193个超级块, centos7 有32768个 超级块大小
dumpe2fs
-h : 查看超级块信息 , 不显示分组信息 在超级块数据有所丢失时 , 可以通过以下命令可以通过备份块回复超级块。
e2fsck -f -b 8193 /dev/hda2
dd if=/dev/zero of=/dev/sdb1 bs=1M count=10
e2fsck -f -b 24577 /dev/sdb1
或者 fsck -a /dev/sdb1使用
fsck会直接调用e2fsck命令
5. VFS
Linux 支持 ext4、XFS、Btrfs、tmpfs、procfs、NFS 等众多文件系统。用户程序不可能为每种文件系统写一套 open_ext4()、open_xfs()——VFS ( Virtual File System ) 就是中间的抽象层。在大部分情况下 , 用户通过libc和kernel的VFS交互 , 不需要关心底层文件系统的具体实现。
vfs的作用。 vfs所隐含的思想是把表示很多不同种类文件系统的共同信息放入内核 ; 其中有一个字段或函数来支持Linux所支持的所有实际文件系统所提供的任何操作。对所调用的每个读、写或其他函数 , 内核都能把它们替换成支持本地Linux文件系统、NTFS文件系统 , 或者文件所在的任何其他文件系统的实际函数。有了vfs , 就能很容易实现不同文件系统之间的数据读写 , 因为它们对外接口都是一样的 , 都是vfs导出的通用接口。

应用程序 : open() / read() / write()
│ ( 统一接口 )
▼
┌─ VFS 层 ( 内核 ) ────────────────┐
│ 4 个核心对象 : │
│ superblock 已挂载的文件系统 │
│ inode 一个文件对象 │
│ dentry 路径目录项缓存 │
│ file 一次打开的对象(fd) │
└───────────────────────────────┘
│ 转发给具体实现
▼
ext4 / XFS / Btrfs / NFS / ...内核把每个读写请求替换成支持本地 ext4、NTFS 或任何其他文件系统的实际函数 , 差异被完全屏蔽在下层 。所以 cat /proc/cpuinfo、cat /var/log/app.log、读 NFS 上的文件 , 用的是完全相同的用户态接口。
6. 日志(Journal)机制
按是否支持日志分类:
三种日志模式(ext3/4)
journal: 元数据+数据都先写日志 , 最安全最慢ordered(默认) : 元数据写日志 , 数据先落盘再写元数据writeback: 只日志元数据 , 最快但可能损坏刚写的数据
7. 创建文件系统
在centos6中默认使用ext4文件系统 , 在centos7中默认使用xfs文件件系统。一般使用mkfs这个命令创建文件系统
在
cenos6安装系统后 , 手工分区ext文件系统无acl功能。需要通过tune2fs -o acl添加对应的ACL功能
7.1 基础命令
7.1.1 mkfs
mkfs(make filesystem) 用于在块设备(分区、LVM、整个磁盘、loop 设备、RAID 设备)上创建文件系统 , 也就是通常所说的"格式化"。 它是 Linux 的通用入口命令 : 本身不实现具体的文件系统逻辑 , 而是根据 -t 指定的类型 , 调用对应的前端工具完成实际工作 :
mkfs -t ext4 /dev/sdb1
│
▼
实际执行的是 ──► /usr/sbin/mkfs.ext4
│
▼
ext4 真正由 mke2fs 实现ls /usr/sbin/mkfs* # 查看系统支持哪些 mkfs 前端
# mkfs.btrfs mkfs.ext2 mkfs.ext3 mkfs.ext4 mkfs.fat
# mkfs.minix mkfs.msdos mkfs.vfat mkfs.xfs mkfs.ntfs ...语法 :
mkfs [OPTIONS] [-t type] [fs-options] device [size]device: 预备检查的硬盘分区 , 例如 :/dev/sda1-V: 详细显示模式-t: 给定档案系统的型式 ,Linux的预设值为ext2同mkfs.type如mkfs.xfs-c: 在制做档案系统前 , 检查该partition是否有坏轨-l bad\_blocks\_file: 将有坏轨的block资料加到bad_blocks_file里面block: 给定block的大小-L "Lable": 设置卷标
7.1.2 mke2fs
mke2fs(make ext2 filesystem ) 用于在设备(分区、磁盘、镜像文件等) 上创建 ext2/ext3/ext4 文件系统。它是 mkfs.ext2、mkfs.ext3、mkfs.ext4 命令的底层实现 , 这几个命令实际上是 mke2fs 的硬链接。
一个文件需要占用一个inode , 同时至少占用一个块。
语法:
mke2fs [选项] 设备 [块数] mke2fs -t ext4 /dev/sdb1 # 最常用的形式选项
常用
-O特性(ext4相关)has_journal # 日志 ( ext3/ext4 必备 ) extents # extent 树 ( ext4 核心 , 替代传统块映射 ) dir_index # 目录索引 , 加速大目录查找 resize_inode # 支持在线扩容 64bit # 支持超大文件系统 huge_file # 支持 >2TB 的单个文件 flex_bg # 灵活的块组布局 metadata_csum # 元数据校验和 ^has_journal # 禁用日志 ( 即 ext2 )使用
-O ^FEATURE关闭指定特性
7.1.3 tune2fs
tune2fs 用于调整已存在的 ext2/ext3/ext4 文件系统的可调参数 , 无需重新格式化。它可以查看/修改卷标、UUID、保留空间、挂载计数、文件系统特性、默认挂载选项等。
语法 :
tune2fs [选项] 设备 tune2fs -l /dev/sdb1 # 查看文件系统信息 ( 最常用 )选项
-l: 查看指定文件系统超级块信息 ;-L 'LABEL': 修改卷标-m #: 修预留给管理员的空间百分比-j: 将ext2升级为ext3-O: 文件系统属性启用或禁用(,–O ^has_journal)tune2fs -O ^has_journal /dev/sdb1 # 去掉日志 ( 变成 ext2 ) tune2fs -O has_journal /dev/sdb1 # 补加日志 ( 变成 ext3 ) tune2fs -O dir_index /dev/sdb1 # 启用目录索引 tune2fs -O ^resize_inode /dev/sdb1 # 禁用在线扩容能力-o: 调整文件系统的默认挂载选项 ,(禁用:–o ^acl)-U UUID: 修改UUID号
示例:
# 1. 查看文件系统当前状态
tune2fs -l /dev/sdb1 | head -20
# 2. 克隆盘后修改 UUID ( 避免冲突 )
tune2fs -U random /dev/sdc1
# 3. 数据盘:取消保留空间 + 关闭定期 fsck
tune2fs -m 0 -c 0 -i 0 /dev/sdb1
# 4. ext2 无损升级为 ext3
tune2fs -j /dev/sdb1
# 5. 高危操作前生成撤销文件
tune2fs -E undo_file=/root/sdb1.undo -O ^has_journal /dev/sdb1
# 后悔时用:e2undo /root/sdb1.undo /dev/sdb1
# 6. 修正错误的最后挂载点记录
tune2fs -M /data /dev/sdb17.1.4 findfs
findfs 用于按卷标 ( LABEL )或UUID 在系统中查找文件系统所在的设备节点 , 是 e2fsprogs 工具包中的一员。它的作用很简单但非常实用:返回 /dev/xxx 这样的设备路径。
语法:
findfs [options] LABEL=<label> findfs [options] UUID=<uuid>
示例:
# 查找成功
$ findfs LABEL=data
/dev/sdb1
# 查找失败 ( 退出码 1 )
$ findfs UUID=12345678-1234-1234-1234-123456789abc
findfs: unable to resolve 'UUID=12345678-...'
# 1. 按卷标查找设备
findfs LABEL=root
# 输出:/dev/mapper/vg0-root
# 2. 按 UUID 查找设备
findfs UUID=3f5c8a2b-9d1e-4f7a-b2c5-8e9d0a1b2c3d
# 输出:/dev/nvme0n1p2
# 3. 在脚本中配合挂载使用
mount "$(findfs LABEL=data)" /mnt/data
# 4. 脚本中判断是否找到 ( 利用退出码 )
if findfs LABEL=backup >/dev/null 2>&1; then
echo "找到备份盘"
else
echo "未找到备份盘"
fi7.1.5 e2label
e2label 用于显示或修改 ext2/ext3/ext4 文件系统的卷标()Volume Label) ,属于 e2fsprogs 工具包。功能上完全等价于 tune2fs -L , 但语法更简单。
e2label device [ new-label ] 修改ext文件系统卷标 示例:
显示卷标
$ e2label /dev/sda1
rootfs
$ e2label /dev/sdb1
# ( 无输出 = 该设备没有设置卷标 )等价查看方式:
tune2fs -l /dev/sdb1 | grep "filesystem volume name"
blkid /dev/sdb1
lsblk -o NAME,LABEL设置/修改卷标
# 设置卷标
e2label /dev/sdb1 data
# 修改已有卷标 ( 直接覆盖 )
e2label /dev/sdb1 backup
# 清除卷标
e2label /dev/sdb1 ""7.2 文件系统修复
7.2.1 e2fsck
文件系统修复的核心工具是 e2fsck(ext2/3/4) , 但完整的能力体系还包括: 事前预防(巡检策略)、事中评估(只读检查)、事后恢复(备份超级块、debugfs 数据抢救)。
语法
e2fsck [选项] 设备运行模式
重要数据 → 先
-n评估 → 用e2image备份元数据 → 再交互或-y修复。退出码
重要选项
五阶段检查流程
e2fsck的修复按固定阶段执行 , 看懂输出日志能判断损坏程度:Pass 1: 检查 inode、块、大小 ← 数据块级损坏 Pass 1D: 检查目录洞 ( dir_index ) Pass 1E: 检查扩展属性 Pass 2: 检查目录结构 ← 目录项损坏 Pass 3: 检查目录连接性 ( / 可达性 ) Pass 4: 检查引用计数 ← 硬链接计数错误 Pass 5: 检查组概要信息 ← 位图不一致典型输出与处理
元数据不一致 , 一般可放心修复 ( y )
Inode 123456, i_blocks is 256, should be 248. Fix<y>?块位图错误 , 修复 ( y )
Block bitmap differences: +12345 ... Fix<y>?孤儿 inode , 修复后文件会出现在
lost+found目录 , 文件名丢失但数据可能还在Unattached inode 234567 ... Connect to /lost+found<y>?
标准修复流程
场景一: 普通数据分区
# 1. 卸载(必须!挂载状态修复是数据灾难的头号原因) umount /dev/sdb1 # 2. 先看磁盘底层有没有坏(可选) badblocks -sv /dev/sdb1 # 只读扫描 # 或合并到 fsck:e2fsck -c -f /dev/sdb1 # 3. 只读评估损伤(可选但强烈建议) e2fsck -n -f /dev/sdb1 # 4. 备份关键元数据(有重要数据时) e2image -r /dev/sdb1 /root/sdb1.meta # -r 只备份元数据 , 很小 # 5. 正式修复(带撤销保险) e2fsck -f -y -z /root/sdb1.undo /dev/sdb1 # 6. 检查退出码 , 确认修复完成 echo $? # 7. 挂载后检查抢救出来的文件 mount /dev/sdb1 /mnt/data ls /mnt/data/lost+found/场景 2 : 根文件系统损坏(系统无法正常启动)
# 方法 A:强制开机自检(能进系统但怀疑有问题) touch /forcefsck # 根分区所在系统 reboot # 开机时 systemd-fsck / e2fsck -p 会自动检查 # 方法 B:从救援模式修复 # 1. 重启进 GRUB → 按 e 编辑启动项 → 在 linux 行尾加: systemd.unit=rescue.target # 2. 进入后根分区只读挂载 , 直接执行: e2fsck -f /dev/mapper/vg0-root # 方法 C:用 Live CD / 安装盘 rescue 模式 # 挂载原系统分区后修复 , 注意别修错设备场景 3: 超级块损坏(报 "
bad magic number")e2fsck /dev/sdb1 # e2fsck: Superblock invalid, trying backup blocks... # 自动尝试备份超级块失败时手动来: # 1. 找备份超级块位置(不要真的格式化 , -n 是演练) mke2fs -n /dev/sdb1 # Superblock backups stored on blocks: # 32768, 98304, 163840, 229376, 294912, ... # 2. 用备份超级块修复(块大小通常 4096) e2fsck -b 32768 -B 4096 /dev/sdb1 # 3. 还不行就逐个尝试后面的备份块 , 或用 debugfs 查看 debugfs -b 32768 /dev/sdb1场景 4 : 只读重挂载(
errors=remount-ro触发)这是内核检测到文件系统错误后的自我保护 ,
dmesg会有EXT4-fs error。处理:# 1. 确认是哪个设备 findmnt / -o SOURCE,FSTYPE dmesg | grep EXT4-fs # 2. 尽快卸载(能 umount 就 umount;不能就停业务后 umount) umount /dev/sda1 # 3. 修复 e2fsck -f /dev/sda1 # 4. 查明根因(常见:磁盘坏道、RAID 掉盘、内存故障、掉电) smartctl -a /dev/sda
7.2.2 fsck
fsck(file system check)是Linux 文件系统检查的前端调度程序(wrapper)。它本身不执行具体检查 , 而是根据文件系统类型调用对应的底层工具——检查 ext4 时实际执行的是 e2fsck , 检查 xfs 时调用 xfs_repair。
你执行: fsck -y /dev/sdb1
实际运行: /sbin/fsck.ext4 -y /dev/sdb1 → e2fsck -y /dev/sdb1语法 :
fsck [选项] [文件系统...]文件系统参数可以是设备(
/dev/sdb1)或挂载点(/data, 会去fstab中查对应设备)。常用选项
作用范围控制
执行方式控制
调试与显示
fstab 每行最后两列控制 fsck 行为 :
/dev/sdb1 /data ext4 defaults 0 2
↑dump ↑pass示例:
日常检查单块盘
umount /dev/sdb1
fsck /dev/sdb1 # 自动识别类型 , 调用 e2fsck
fsck -t ext4 /dev/sdb1 # 显式指定类型(探测失败时用)修复模式
fsck -y /dev/sdb1 # 全自动修复(数据不重要时)
fsck -n /dev/sdb1 # 只读评估(数据重要时 , 先评估再决定)
fsck -r /dev/sdb1 # 交互式批量检查
fsck -A # 按 fstab 全量检查(开机逻辑)
fsck -AR # 检查除根分区外的所有分区
fsck -A -M -T # 跳过已挂载的 , 静默批量巡检进度显示
fsck -C 0 /dev/sdb1 # 进度条输出到终端(大容量盘必备)开机自检的现代机制