Linux核心技术:Linux文件系统与bootFS/rootFS
云原生学习路线导航页(持续更新中)
- kubernetes学习系列快捷链接
- Kubernetes架构原则和对象设计(一)
- Kubernetes架构原则和对象设计(二)
- Kubernetes架构原则和对象设计(三)
- Kubernetes控制平面组件:etcd(一)
- Kubernetes控制平面组件:etcd(二)
- Kubernetes控制平面组件:API Server详解(一)
- Kubernetes常见问题解答
- 查看云机器的一些常用配置
本文是 Linux核心技术 系列文章:Linux文件系统与bootFS/rootFS,主要讲解了文件系统的概念、linux文件系统的设计、linux标准目录、什么是挂载、linux的bootFS与rootFS等
- 希望大家多多 点赞 关注 评论 收藏,作者会更有动力继续编写技术文章
1.Linux文件系统
1.1.什么是文件系统?
1.1.1.文件系统的本质
- 想象你有一个大仓库(硬盘),里面堆满了各种货物(数据)。如果没有明确的分类和标签,你根本找不到想要的东西。
- 文件系统(File System)就是管理这些数据的“仓库管理员”,负责:
- 存储:数据放在哪里
- 查找:如何快速找到数据
- 保护:防止数据被随意修改
- 组织:目录结构、权限控制
1.1.2.为什么需要文件系统?
- 原始硬盘只是一堆0和1:没有结构,无法直接使用
- 解决核心问题:
- 如何区分不同类型的数据(文本、图片、程序)?
- 如何保证数据不丢失、不被随意覆盖?
- 如何让多个程序同时安全地读写数据?
1.2.Linux文件系统的设计哲学
1.2.1.“一切皆文件”(Everything is a File)
-
这是Linux最独特的设计思想!
- 普通文件:你创建的文档、图片
- 目录:存放文件的“文件夹”
- 硬件设备:键盘、鼠标、U盘(比如
/dev/sda
表示硬盘) - 进程信息:运行中的程序状态(比如
/proc/1234
表示PID为1234的进程) - 网络连接:甚至可以通过文件操作网络(比如
/dev/tcp
)
-
设计原因:
- 统一操作接口!无论操作什么,都可以用
open()
、read()
、write()
等相同函数处理,极大简化了系统设计。
- 统一操作接口!无论操作什么,都可以用
1.2.2.树形目录结构
- Linux的目录像一棵倒挂的树,根目录(
/
)是起点:/ ├── bin → 基础命令(如ls, cp) ├── etc → 配置文件 ├── home → 用户的家目录 ├── dev → 设备文件 ├── tmp → 临时文件 └── ...
- 为什么这样设计?
- 标准化:所有Linux系统目录结构一致,方便软件开发和维护
- 隔离性:系统文件(
/bin
)和用户文件(/home
)分开,避免误操作
1.3.文件系统的核心概念详解
1.3.1. 文件类型
-
Linux有7种文件类型(用
ls -l
查看第一个字符):类型符号 说明 例子 -
普通文件 .txt、.jpg d
目录(文件夹) /home l
符号链接(快捷方式) /usr/bin/python → python3 c
字符设备(键盘、终端) /dev/tty b
块设备(硬盘、U盘) /dev/sda s
套接字(网络通信) /run/docker.sock p
管道(进程间通信) 无具体路径 -
设计原因:用统一的方式管理所有资源,比如读写硬件就像读写普通文件!
1.3.2.Inode:文件的“身份证”
- 每个文件对应一个唯一的inode,存储元数据:
- 文件大小、权限、所有者、时间戳
- 数据在硬盘上的物理位置
- 但不存储文件名!
- 查看inode:
ls -i filename
- 为什么需要inode?
- 想象图书馆每本书有一个唯一编号(inode),而书名可以随意修改(文件名)。这样即使重命名文件,系统也能快速找到数据位置。
1.3.3.硬链接 vs 软链接
硬链接(Hard Link) | 软链接(Symbolic Link) | |
---|---|---|
本质 | 直接指向inode | 独立文件,存储目标路径 |
特点 | 不能跨文件系统,删除源文件仍可访问 | 可以跨文件系统,源文件删除后失效 |
创建命令 | ln source.txt hardlink | ln -s source.txt softlink |
类比 | 同一本书的两个不同书名 | 书架的便签条,指向另一本书 |
- 设计原因:硬链接节省空间(不重复存储数据),软链接更灵活(可跨设备)。
1.4.目录结构的秘密
1.4.1.目录完整分类表
类别 | 目录 | 作用 | 特点 | 关键文件/功能 | 示例 |
---|---|---|---|---|---|
系统核心 | / | 所有目录的起点 | 不可直接存储文件 | 仅包含子目录 | 无 |
系统核心 | /bin | 基础系统命令(所有用户可用) | 单用户模式可用、静态可执行文件 | ls , cp , bash , rm | 系统修复时使用的核心命令 |
系统核心 | /boot | 系统启动文件 | 只读、关键启动文件 | 内核文件 vmlinuz-* , 引导加载程序(GRUB) | /boot/grub/grub.cfg |
硬件设备 | /dev | 设备文件接口 | 动态生成、无实际大小 | /dev/sda (硬盘), /dev/tty (终端), /dev/null (黑洞设备) | 通过 mknod 创建设备文件 |
配置管理 | /etc | 系统级配置文件 | 纯文本配置、禁止可执行文件 | /etc/passwd (用户信息), /etc/fstab (挂载表), /etc/ssh/sshd_config | Nginx 配置 /etc/nginx/nginx.conf |
用户数据 | /home | 普通用户私有目录 | 用户自主管理、权限隔离 | 用户配置文件(~/.bashrc ), 个人文档 | /home/alice/Documents |
系统库 | /lib | 32位系统库文件 | 系统运行依赖库 | C 标准库 libc.so.6 , 内核模块 /lib/modules/ | 驱动程序模块 /lib/modules/5.15.0-78-generic/kernel/ |
系统库 | /lib64 | 64位系统库文件 | 64位系统专用 | 同 /lib | 仅存在于64位系统 |
存储挂载 | /media | 自动挂载可移动设备 | 用户友好访问点 | 自动挂载的U盘、光盘 | 插入U盘后自动挂载到 /media/MyUSB |
存储挂载 | /mnt | 临时手动挂载点 | 管理员临时挂载 | 手动挂载的NFS共享或硬盘分区 | sudo mount /dev/sdb1 /mnt |
第三方软件 | /opt | 独立商业软件安装目录 | 自包含软件包 | 大型商业软件、独立发行程序 | /opt/google/chrome , /opt/oracle/ , /opt/cni |
系统信息 | /proc | 实时进程与内核信息 | 虚拟文件系统、动态更新 | /proc/cpuinfo (CPU信息), /proc/[PID]/ (进程详情) | 查看内存使用:cat /proc/meminfo |
特权隔离 | /root | 管理员家目录 | 仅root可访问 | root用户的配置文件 | /root/.ssh/ |
运行时数据 | /run | 系统运行时临时文件 | 内存驻留、重启消失 | 进程PID文件、套接字文件 | /run/sshd.pid , /run/docker.sock |
系统管理 | /sbin | 系统管理命令 | 需root权限执行 | fdisk (磁盘分区), iptables (防火墙), reboot (重启) | 系统维护工具 |
服务数据 | /srv | 服务相关数据 | 明确服务归属 | Web服务内容、FTP数据 | /srv/http/ (网站根目录), /srv/ftp/ |
硬件管理 | /sys | 内核设备与参数管理 | 虚拟文件系统、硬件调控接口 | /sys/class/net/ (网络接口), /sys/devices/ (设备树) | 调整CPU频率:/sys/devices/system/cpu/ |
临时存储 | /tmp | 临时文件存储 | 全局可写、定期清理 | 应用程序临时文件 | 浏览器缓存文件 /tmp/chromium-xxxxx |
用户程序 | /usr | 用户级程序与资源 | 只读、跨系统共享 | /usr/bin (用户命令), /usr/lib (库文件), /usr/share (共享数据) | Python解释器 /usr/bin/python3 |
动态数据 | /var | 可变数据存储 | 持续增长、需要定期维护 | /var/log (日志), /var/lib (数据库), /var/cache (缓存) | MySQL数据文件 /var/lib/mysql/ |
文件恢复 | /lost+found | 文件系统修复残留文件 | 仅ext3/4文件系统存在 | fsck 修复后的文件碎片 | 系统崩溃后恢复的碎片文件 |
软件包管理 | /snap | Snap软件包存储(Ubuntu专用) | 容器化软件包 | Snap应用文件 | /snap/chromium/ |
1.4.2.为什么需要这么多目录?
- 安全性:系统文件(
/bin
)和用户文件(/home
)隔离,避免误删 - 可维护性:日志单独放在
/var/log
,方便查找和管理 - 标准化:所有Linux发行版目录结构一致,软件兼容性更好
1.5.权限管理:保护你的数据
1.5.1.文件权限的三组角色
- 所有者(Owner):文件的主人
- 所属组(Group):一组用户的集合
- 其他人(Others):既不是主人,也不在组里
1.5.2.权限类型
符号 | 权限 | 对文件的影响 | 对目录的影响 |
---|---|---|---|
r | 读 | 可以查看文件内容 | 可以列出目录中的文件 |
w | 写 | 可以修改文件内容 | 可以创建/删除目录中的文件 |
x | 执行 | 可以运行程序(如脚本) | 可以进入目录(比如cd 命令) |
- 示例:
-rwxr-xr--
表示:- 第一位:文件类型
- 所有者有读、写、执行权限
- 所属组有读、执行权限
- 其他人只有读权限
1.5.3.为什么需要权限?
- 多用户系统:Linux设计初衷是多人同时使用服务器,必须防止用户互相干扰
- 系统安全:关键系统文件(如
/etc/passwd
)不能被随意修改
1.6.挂载(Mount):扩展你的存储空间
1.6.1.什么是挂载?
-
把U盘插入电脑后,Linux不会自动显示文件。你需要将设备关联到一个目录(挂载点),才能访问其中的数据。
-
操作示例:
# 创建挂载点 sudo mkdir /mnt/usb# 挂载U盘(假设设备是/dev/sdb1) sudo mount /dev/sdb1 /mnt/usb# 访问U盘内容 ls /mnt/usb# 卸载 sudo umount /mnt/usb
1.6.2.为什么需要挂载?
- 灵活性:可以动态连接/断开存储设备
- 统一访问:所有存储设备都通过目录访问,无需关心物理位置
1.7.动手实验:加深理解
1.7.1.查看文件inode
touch test.txt # 创建文件
ls -i test.txt # 查看inode号
stat test.txt # 显示详细元数据
1.7.2.理解软硬链接
echo "Hello" > original.txt
ln original.txt hardlink # 创建硬链接
ln -s original.txt softlink # 创建软链接# 删除原文件后观察区别
rm original.txt
cat hardlink # 仍然能读取内容
cat softlink # 报错"文件不存在"
2.Linux 的 bootFS 和 rootFS
- Linux系统,一般会包含两个文件系统fs
- Bootfs,其中有一个Bootloader,在机器启动时负责引导加载kernel。当kernel加载到内存后,会把bootfs umount掉,相当于卸载
- 然后再去加载rootfs,即各种标准目录。linux不同发型版,rootfs可能有些差异,但bootfs(kernel)基本一致
2.1.核心概念对比
特性 | bootFS | rootFS |
---|---|---|
全称 | Boot File System(引导文件系统) | Root File System(根文件系统) |
作用阶段 | 系统启动阶段 | 系统运行阶段 |
核心内容 | 内核(Kernel)、initramfs/initrd | 操作系统根目录(/bin , /etc , /usr 等) |
存储位置 | 独立分区(如 /boot )或内存 | 磁盘分区(如 / )或容器镜像层 |
生命周期 | 临时加载,启动完成后卸载 | 持久存在,系统运行时持续使用 |
典型大小 | 较小(几十MB到几百MB) | 较大(几GB到几十GB) |
2.2.bootFS详解
2.2.1.核心组件
- 内核(Kernel):
- Linux 系统的核心,负责硬件管理和进程调度。文件通常命名为
vmlinuz-<版本>
。 - 系统启动成功后,还能在/boot中看到内核文件,比如:我当前的系统即为 5.4.241-1-tlinux4-0017.4 内核版本
[root@VM-226-235-tencentos /opt]# ll /boot/vmlinuz-5.4.241-1-tlinux4-0017.4 -rw-r--r-- 1 root root 9160864 Oct 7 2023 /boot/vmlinuz-5.4.241-1-tlinux4-0017.4
- 5:主版本号(重大功能更新)
- 4:次版本号(新增功能)
- 241:修订号(错误修复)
- 1:发行版定制补丁次数
- tlinux4:内核类型,tencentOS-linux
- Linux 系统的核心,负责硬件管理和进程调度。文件通常命名为
- initramfs/initrd:
- 临时根文件系统(Initial RAM File System),包含启动阶段必需的驱动和工具。
- initramfs:基于 cpio 格式,直接嵌入内核(现代系统使用)
- initrd:独立加载的磁盘映像(旧系统使用)
- 临时根文件系统(Initial RAM File System),包含启动阶段必需的驱动和工具。
2.2.2.启动流程中的角色
- BIOS/UEFI 加载引导程序(如 GRUB)
- 引导程序 加载
bootFS
中的内核和 initramfs - 内核 解压 initramfs 到内存,挂载为临时根文件系统
- initramfs 中的脚本执行以下操作:
- 加载硬件驱动(如磁盘控制器、文件系统驱动)
- 挂载真正的
rootFS
- 切换根目录到
rootFS
- 卸载
bootFS
,进入系统正常运行阶段
2.2.3.设计意义
- 硬件兼容性:允许在挂载真实根文件系统前加载必要驱动
- 灵活性:支持加密根文件系统、网络挂载等复杂场景
- 轻量化:避免将全部驱动编译进内核
2.3.rootFS详解
2.3.1.核心组成
目录 | 作用 | 是否必需 |
---|---|---|
/bin | 基础命令(如 ls , bash ) | 是 |
/etc | 配置文件 | 是 |
/lib | 共享库文件 | 是 |
/dev | 设备文件 | 内核自动生成 |
/proc | 进程与内核信息 | 虚拟文件系统 |
/usr | 用户级程序与资源 | 否(可网络挂载) |
/var | 可变数据(日志、缓存等) | 否 |
2.3.2.运行时的角色
- 进程树起点:所有进程的父进程(如
systemd
或init
)从 rootFS 启动 - 环境隔离:chroot 操作基于 rootFS 实现环境隔离
- 容器基础:Docker 镜像本质上是裁剪版的 rootFS
2.3.3.rootFS 的类型
类型 | 描述 | 应用场景 |
---|---|---|
磁盘 rootFS | 存储在硬盘分区的传统根文件系统 | 物理机/虚拟机 |
内存 rootFS | 完全载入内存的临时文件系统 | 救援模式、Live CD |
容器 rootFS | 每个容器都有自己独立的rootFS,与主机分离 | Docker/容器运行时 |
2.4.理解Docker容器的bootFS与rootFS
2.4.1.Docker容器与传统Linux系统的 关键差异
组件 | 传统 Linux 系统 | Docker 容器 |
---|---|---|
bootFS | 必需(包含内核) | 不需要(复用宿主机内核) |
rootFS | 完整操作系统文件 | 裁剪版(仅包含应用所需文件) |
- docker容器
- docker容器本质上就是运行在宿主机上的一个进程,只不过通过namespace、cgroups等技术将之隔离成一个独立的环境。但它依旧只是一个进程而已
- 作为一个进程,docker容器不需要自行加载kernel,所以不需要bootFS,只需要自己运行的 rootFS 即可
- 传统Linux系统/虚拟机
- 本质上是一个完整独立的linux系统,所以需要从头开始启动linux系统,需要bootFS
2.4.2.怎么在主机上查看docker的rootFS?
- 在主机上,找到容器的进程pid,即可在/proc/${pid}中看到这个进程相关的数据,其中 /root目录一般就是容器的 rootFS
- 与进入容器ls查看到的目录和文件是一样的
# 宿主机 ls /proc/${pid}/root# docker exec -it ${container-id} -- ls
2.5.关键问题解答
2.5.1.为什么容器不需要 bootFS?
- 内核共享:容器与宿主机共享内核,无需独立内核和 initramfs
- 启动方式:容器进程直接由宿主机 init 系统(如 systemd)启动
2.5.2.如何定制 rootFS?
- 手动构建:
# 使用 debootstrap 创建最小化 rootFS sudo debootstrap focal ./my-rootfs http://archive.ubuntu.com/ubuntu
- 容器构建:
FROM scratch COPY my-rootfs/ / CMD ["/bin/bash"]