Linux系统中那些重要的文件路径

1.Linux 文件目录结构列表

文件系统层次标准 (Filesystem Hierarchy Standard, FHS)是一个定义了Linux和其他类Unix操作系统中目录结构和目录内容的标准。当前版本为FHS 3.0,由Linux Foundation维护。

Linux文件系统采用层次化的目录结构,这种设计遵循了Unix哲学中的"一切皆文件"原则。

与 Windows 系统不同,Linux 的文件系统采用单一的树形结构,从根目录(/)开始,所有文件和目录都在其下。

根目录(/)

根目录(/)是 Linux 文件系统的顶层目录。所有的文件和目录都从这里开始,形成一个树形结构。根目录下的每个子目录都有其特定的功能和用途。

  • /bin :存放基本用户命令

  • /sbin :存放系统管理命令

  • /etc:存放系统配置文件。

  • /dev:存放设备文件。

  • /tmp:存放临时文件。

  • /home:存放用户主目录。

  • /var:存放可变数据文件。

  • /usr :存放用户级应用程序和文件

  • /opt:存放附加软件包。

  • /mnt :用于临时挂载文件系统

  • /media:用于自动挂载的可移动设备。

  • /boot :存放启动加载程序和内核文件

  • /lib :存放系统库文件和内核模块

  • /proc :存放系统内核和进程信息

  • /sys :存放系统设备和内核信息

  • /root:超级用户的主目录。

下面逐一详细介绍这些目录及其子目录的具体用途和常见文件。

/bin 目录

/bin(binary)目录包含系统启动和单用户模式下使用的基本命令。这些命令是系统正常运行所必需的,并且在单用户模式或系统紧急修复时也可以使用。

常见的命令包括:

  • ls:列出目录内容。

  • cp:复制文件或目录。

  • mv:移动或重命名文件或目录。

  • rm:删除文件或目录。

  • cat:连接文件并显示输出。

  • echo:显示消息。

  • mkdir、rmdir、pwd、grep等等基本命令。

这些命令通常是静态链接的,确保在系统启动时不依赖于其他库文件。

补充知识:

ls # 列出目录内容

cat # 显示文件内容

cp # 复制文件

mv # 移动/重命名文件

rm # 删除文件

mkdir # 创建目录

rmdir # 删除空目录

pwd # 显示当前目录

grep # 文本搜索

sed # 流编辑器

awk # 文本处理工具

/sbin 目录

/sbin(system binary)目录包含系统管理命令,这些命令通常需要超级用户root权限执行。它们用于系统启动、维护和修复。

常见的命令包括:

  • ifconfig:配置网络接口。

  • reboot:重启系统。

  • shutdown:关闭系统。

  • fdisk:磁盘分区工具。

  • mkfs:创建文件系统。

这些命令对于系统管理员来说是至关重要的,因为它们涉及到系统的核心功能和配置。

补充知识:

fsck # 文件系统检查

mount # 挂载文件系统

umount # 卸载文件系统

ifconfig # 网络接口配置

iptables # 防火墙配置

service # 服务管理

systemctl # systemd服务管理

/etc 目录

/etc 目录包含所有的系统全局配置文件。这些文件定义了系统的各种设置和参数。

常见的配置文件和目录包括:

  • /etc/passwd:用户账号信息文件。

  • /etc/fstab:文件系统挂载表。

/etc/fstab文件定义了系统启动时自动挂载的文件系统。

fstab格式:

复制代码
设备/UUID  挂载点  文件系统类型  挂载选项  dump  fsck

检查fstab语法

mount -a

重新挂载文件系统

mount -o remount /home

查看UUID

blkid

  • /etc/hosts:主机名和 IP 地址对应表。

  • /etc/hostname:定义系统的主机名。

  • /etc/network/interfaces:网络接口配置文件(在基于 Debian 的系统中)。

在 /etc 目录中,每个服务和应用程序通常都有自己的子目录或配置文件,例如 Apache 的配置文件在 /etc/apache2/ 下。

补充:

/etc/passwd # 用户账户信息

/etc/shadow # 用户密码信息

/etc/group # 用户组信息

/etc/hosts # 主机名解析

/etc/fstab # 文件系统表

/etc/crontab # 系统定时任务

/etc/sudoers # sudo权限配置

/etc/ssh/ # SSH配置目录

/etc/network/ # 网络配置目录

/etc/systemd/ # systemd配置目录

/etc/init.d/ # 初始化脚本(SysV)

/etc/systemd/ # systemd配置

/etc/cron.d/ # cron任务配置

/etc/logrotate.d/ # 日志轮转配置

/etc/security/ # 安全配置

/etc/default/ # 默认配置

/dev 目录

/dev 目录包含设备文件,这些文件表示系统中的各种硬件设备。Linux 中的一切皆文件,包括硬件设备。

常见的设备文件包括:

  • /dev/sda:第一个 SCSI 硬盘。

  • /dev/tty:终端设备。

  • /dev/null:空设备,丢弃所有写入其中的数据。

  • /dev/random:随机数生成器。

这些设备文件允许用户和应用程序以文件的方式访问硬件设备。

补充:

/dev/sda # 第一个SCSI硬盘

/dev/sda1 # 第一个SCSI硬盘的第一个分区

/dev/null # 空设备

/dev/zero # 零设备

/dev/random # 随机数设备

/dev/urandom # 伪随机数设备

/dev/tty # 当前终端

/dev/pts/ # 伪终端目录

/tmp 目录

/tmp 目录用于存放临时文件。系统和应用程序在运行过程中可能会在此目录下创建临时文件。通常,系统会在每次启动时清理 /tmp 目录,以防止磁盘空间被临时文件占用过多。

/tmp 目录中的文件通常对所有用户可读写,但应注意临时文件的权限和安全性。

/home 目录

/home 目录是用户的主目录,每个用户在 /home 目录下都有一个以其用户名命名的子目录。用户的所有个人文件和配置文件都存放在这个子目录中。例如,用户 john 的主目录为 /home/john

常见的文件和子目录包括:

  • ~/Documents:用户的文档目录。

  • ~/Downloads:用户的下载目录。

  • ~/Pictures:用户的图片目录。

  • ~/.bashrc:Bash Shell 配置文件。

  • ~/.profile:用户的环境设置文件。

用户目录的权限设置通常是这样的,只有该用户和超级用户(root)可以访问和修改其内容。这可以保护用户的隐私和数据安全。

补充:

/home/username/.bashrc # bash配置文件

/home/username/.bash_profile # bash登录配置

/home/username/.ssh/ # SSH密钥目录

/home/username/.vimrc # vim配置文件

/home/username/Documents/ # 文档目录

/home/username/Downloads/ # 下载目录

/var 目录

/var 目录用于存放系统运行时产生的可变数据。不同于 /etc 目录中的配置文件,/var 中的数据是动态变化的。

常见的子目录和文件包括:

  • /var/log :系统日志文件目录。常见的日志文件有 /var/log/syslog(系统日志)、/var/log/auth.log(认证日志)、/var/log/kern.log(内核日志)等。

这是运维人员最常访问的目录之一。

重要日志文件

/var/log/messages # 系统消息日志

/var/log/syslog # 系统日志

/var/log/auth.log # 认证日志

/var/log/kern.log # 内核日志

/var/log/cron.log # cron任务日志

/var/log/apache2/ # Apache日志目录

/var/log/nginx/ # Nginx日志目录

/var/log/mysql/ # MySQL日志目录

  • /var/mail:用户邮件存放目录。

  • /var/spool:队列目录,用于存放打印任务、邮件队列等。

包含等待处理的任务队列。

/var/spool/cron # cron任务队列

/var/spool/mail # 邮件队列

/var/spool/cups # 打印队列

  • /var/cache:应用程序缓存文件。

  • /var/www:Web 服务器的根目录,存放网站文件。

/var 目录中的数据可能会迅速增长,因此需要定期清理和维护,以防止磁盘空间不足。

/usr 目录

/usr 目录用于存放用户级应用程序和文件。这是一个非常重要的目录,包含了大量的二进制文件、库文件、文档和其他资源。

常见的子目录包括:

  • /usr/bin :用户级命令的二进制文件。常见的命令有 gcc(GNU 编译器)、perl(Perl 解释器)等。

gcc # C编译器

python # Python解释器

vim # 文本编辑器

ssh # 安全外壳

wget # 网络下载工具

curl # 数据传输工具

  • /usr/sbin:系统管理命令的二进制文件。与 /sbin 类似,但这些命令不是启动时必须的。

系统管理命令示例

cron # 定时任务守护进程

sshd # SSH守护进程

httpd # HTTP服务器

nginx # Web服务器

  • /usr/lib:库文件目录,存放应用程序和系统所需的共享库。

  • /usr/share:共享数据目录,存放不特定于某个用户或系统的共享数据,如文档、图标、声音等。

  • /usr/local:本地安装的软件和文件。用户可以在不影响系统其他部分的情况下安装和管理软件。

/usr/local/bin - 本地命令

/usr/local/sbin - 本地系统命令

/usr/local/lib - 本地库文件

/usr/local/share - 本地共享数据

/usr/local/etc - 本地配置文件

/usr 目录中的内容通常由系统包管理器管理,如 apt、yum 等。

补充:

/usr/bin - 用户命令

/usr/sbin - 系统管理命令

/usr/lib - 库文件

/usr/lib64 - 64位库文件

/usr/include - C头文件

/usr/share - 共享数据

/usr/local - 本地软件安装

/usr/src - 源代码

/opt 目录

/opt 目录用于安装附加软件包。通常,第三方软件或自定义应用程序会安装在此目录下。

每个软件通常会在 /opt 下有一个独立的子目录,例如 /opt/software。这种方式可以避免与系统的其他部分产生冲突,并便于管理和卸载。

补充:

/opt/oracle/ # Oracle数据库

/opt/google/ # Google软件

/opt/vmware/ # VMware软件

/opt/teamviewer/ # TeamViewer软件

/mnt 目录

/mnt 目录用于临时挂载文件系统。

系统管理员可以将外部存储设备(如 USB 驱动器、网络文件系统等)挂载到 /mnt 下的某个子目录中。例如,可以使用 mount /dev/sdb1 /mnt/usb 将一个 USB 驱动器挂载到 /mnt/usb

补充:

临时挂载设备

mkdir /mnt/usb

mount /dev/sdb1 /mnt/usb

挂载网络文件系统

mkdir /mnt/nfs

mount -t nfs server:/path /mnt/nfs

卸载

umount /mnt/usb

/media 目录

/media 目录用于自动挂载的可移动设备,如光盘、U 盘等。

当这些设备插入时,系统会自动将其挂载到 /media 下的一个子目录中。例如,插入一个 U 盘后,系统可能会在 /media/user/USB 下自动创建一个目录并挂载该设备。

补充:

查看挂载的媒体设备

ls /media/

检查挂载状态

mount | grep /media

/boot 目录

/boot 目录包含启动加载程序和内核文件。

系统启动时,启动加载程序(如 GRUB)会从这里加载内核和其他必要文件。

常见文件包括:

  • vmlinuz:压缩的 Linux 内核镜像文件。

  • initrd.img:初始 RAM 盘,用于启动时加载必要的驱动程序和文件系统。

  • grub:GRUB 启动加载程序的配置文件和模块。

/boot 目录中的文件对于系统启动至关重要,因此应谨慎修改。

补充:

/boot/vmlinuz-* # 内核映像文件

/boot/initrd.img-* # 初始RAM磁盘

/boot/System.map-* # 内核符号表

/boot/config-* # 内核配置文件

/boot/grub/ # GRUB启动加载器

/lib 目录

/lib目录包含系统启动和运行/bin/sbin中程序所需的共享库文件。

/lib 目录包含系统库文件和内核模块。系统启动时,许多关键程序依赖于这些库文件。常见的库文件包括 C 标准库(libc.so)、动态链接器(ld-linux.so)等。内核模块(如文件系统驱动、硬件驱动)通常位于 /lib/modules 目录中。

/lib/libc.so.6 # C标准库

/lib/libm.so.6 # 数学库

/lib/libpthread.so.0 # 线程库

/lib/modules/ # 内核模块

查看库文件依赖

ldd /bin/ls

查看内核模块

ls /lib/modules/$(uname -r)/

加载内核模块

modprobe modulename

/proc 目录

/proc 目录是一个虚拟文件系统,包含系统内核和进程信息。这个目录中的内容并不实际存在于磁盘上,而是由内核在运行时动态生成的。/proc 目录提供了一种方便的方式来访问系统信息和进程数据。

常见的文件和目录包括:

  • /proc/cpuinfo:显示 CPU 的信息,包括型号、速度和核心数。

  • /proc/meminfo:显示内存使用情况,包括总内存、可用内存和缓存。

  • /proc/uptime:显示系统的运行时间和空闲时间。

  • /proc/[pid]/:每个运行中的进程都有一个以其 PID(进程标识符)命名的子目录,包含该进程的详细信息,如状态、内存映射、打开的文件等。

/proc 目录中的信息对于系统管理员和开发者来说非常重要,因为它提供了对系统运行状态的实时监控和调试工具。

补充:

/proc/cpuinfo # CPU信息

/proc/meminfo # 内存信息

/proc/version # 内核版本

/proc/uptime # 系统运行时间

/proc/loadavg # 系统负载

/proc/mounts # 挂载信息

/proc/net/ # 网络统计

/proc/sys/ # 系统参数

/sys 目录

/sys 目录是另一个虚拟文件系统,提供系统设备和内核信息。

与 /proc 类似,/sys 目录中的内容也是由内核在运行时动态生成的。/sys 目录主要用于提供内核与用户空间之间的接口,允许用户查看和配置硬件设备。

常见的文件和目录包括:

  • /sys/class/:分类显示不同类型的设备,如网络设备(/sys/class/net)、块设备(/sys/class/block)等。

  • /sys/devices/:显示系统中的所有设备,以设备树的形式组织。

  • /sys/module/:显示已加载的内核模块及其参数。

通过 /sys 目录,用户和管理员可以方便地管理和配置系统硬件,进行性能调优和故障排除。

补充:

/sys/block/ # 块设备信息

/sys/class/ # 设备类别信息

/sys/devices/ # 设备树信息

/sys/kernel/ # 内核信息

/sys/module/ # 模块信息

/root 目录

/root 目录是超级用户(root)的主目录。

与普通用户的主目录位于 /home 下不同,root 用户的主目录直接位于根目录下。这是因为 root 用户需要在单用户模式下进行系统维护和修复,/root 目录可以在没有挂载其他文件系统的情况下访问。常见的文件和目录包括:

  • /root/.bashrc:root 用户的 Bash Shell 配置文件。

  • /root/.profile:root 用户的环境设置文件。

root 用户拥有系统的最高权限,因此 /root 目录中的文件和配置通常只有 root 用户本身可以访问和修改。

符号链接(Symbolic Link)

符号链接是一种特殊的文件,它指向另一个文件或目录。符号链接可以简化文件路径访问和管理。创建符号链接的命令是 ln -s,例如:

复制代码
ln -s /path/to/target /path/to/link

符号链接在文件目录结构中具有重要作用,尤其是在需要在多个位置访问同一文件或目录时。符号链接可以跨文件系统边界,并且可以指向目录或文件。

/run 目录

/run目录包含系统运行时的数据。

/run 目录是一个临时文件系统,用于存放系统运行时的状态文件和进程信息。

它是在系统启动时动态创建的,并且其内容在每次启动时都会被清空。

常见的文件和目录包括:

  • /run/lock:用于锁文件,防止多个进程同时访问同一个资源。

  • /run/user/:用于用户相关的运行时数据,每个用户都有一个以其 UID 命名的子目录。

/run 目录中的文件和目录通常由系统服务和守护进程使用,提供了一种轻量级的进程间通信方式。

/srv 目录

/srv 目录用于存放服务相关的数据。

srv 是 "service" 的缩写,表示该目录用于存放系统提供的各种服务的数据。例如,Web 服务器的文件可以存放在 /srv/www 下,FTP 服务器的文件可以存放在 /srv/ftp 下。/srv 目录结构可以根据具体服务的需求进行自定义。

/srv/www/ # Web服务数据

/srv/ftp/ # FTP服务数据

/srv/git/ # Git仓库

/lost+found 目录

/lost+found 目录存在于每个使用 ext 文件系统(如 ext2、ext3、ext4)的文件系统根目录下。它用于存放文件系统在崩溃或损坏后恢复的文件碎片。当文件系统进行 fsck(文件系统一致性检查)时,找回的孤立文件会被放置在 /lost+found 目录中。系统管理员可以在检查后决定如何处理这些文件。


2.Linux 文件系统的核心设计理念

与 Windows 的"C/D/E 盘"不同,Linux 坚持 单一树形结构 + 挂载机制的设计哲学,把本地磁盘、U 盘、网络存储、甚至虚拟设备都统一在一棵目录树下。

这种架构不仅简洁优雅,还让 文件访问、硬件交互、系统配置全部走一套通用接口,真正体现了"一切皆文件"的思想。

本文将带你从理念入手,逐层拆解 Linux 文件系统的核心逻辑:三大设计原则、标准目录层级、文件类型分类、底层工作机制,并结合实操命令帮助你理解。


2.1 Linux 文件系统的核心理念

Linux 继承了 Unix 的文件系统哲学,其架构设计遵循三大核心原则,这些原则是理解后续层级结构的基础:

1️⃣ 一切皆文件(Everything is a File)

这是 Linux 最经典的设计理念之一。

在 Linux 中,不仅普通文档、图片是文件,硬件设备(如硬盘、鼠标、打印机)、进程间通信接口(如管道、socket)、甚至目录本身,都被抽象为 "文件" 。

这种统一的抽象模型,让操作系统可以用一套相同的接口(如 open()、read()、write()、close() 等系统调用)处理所有资源,极大简化了底层逻辑与上层应用开发。

例如:

  • 硬盘分区对应 /dev/sda1、/dev/nvme0n1p2 等 "设备文件";

  • 内存信息通过 /proc/meminfo 这一 "伪文件" 暴露给用户;

  • 打印机设备对应 /dev/lp0 等 "字符设备文件"。

2️⃣ 单一树形目录结构(Single Tree Hierarchy)

与 Windows 中 "C 盘、D 盘、E 盘" 的多根目录不同,Linux 只有一个根目录 \(正斜杠),所有存储设备(本地硬盘、U 盘、网络共享盘)都需通过**"挂载"**(Mount)方式,关联到根目录下的某个子目录(如 /mnt/usb、/media/share),最终形成一个完整的、无分支的树形结构。

这种设计的优势在于:

  • 资源路径统一:任何文件的路径都从根目录出发(如 /home/user/docs/report.pdf),无需区分 "盘符";

  • 跨设备访问透明:用户访问 /mnt/usb/photo.jpg 时,无需关心该文件实际存储在 U 盘中,操作系统会自动处理设备切换。

3️⃣ 挂载机制(Mounting)

"挂载" 是 Linux 整合不同存储设备的核心手段。

本质上,它是将一个文件系统(如 U 盘的 FAT32、硬盘分区的 Ext4)与根目录下的某个 "挂载点"(Mount Point,即一个空目录)建立关联的过程。

挂载后,访问挂载点目录就等同于访问该设备的文件系统。

例如:

  • 将 U 盘(设备文件 /dev/sdb1)挂载到 /mnt/usb 后,ls /mnt/usb 会显示 U 盘中的所有文件;

  • 卸载(Umount)时,需先确保没有进程正在访问该挂载点,否则会提示 "设备忙"。


2.2Linux 文件的类型

在 Linux 中,"文件" 并非仅指普通文档,而是根据功能分为多种类型,通过 ls -l 命令可查看文件类型(输出结果的第一个字符代表类型):

🌱 普通文件(-,Regular File)

最常见的文件类型,用于存储文本、二进制数据、图片、视频等。

例如:

  • 文本文件:/etc/passwd、/home/user/note.txt;

  • 二进制文件:/bin/ls(可执行命令)、/usr/bin/chrome(应用程序);

  • 压缩文件:archive.tar.gz、image.zip。

验证命令:

  • file [文件路径]:显示文件的具体格式(如文本、ELF 二进制、压缩包);

  • stat [文件路径]:输出中 File type 字段明确标记为 regular file,且有完整的大小、修改时间等属性。


🌱 目录文件(d,Directory)

用于存储其他文件或子目录的 "容器",本质是记录文件名与对应 inode 编号的列表。

例如/home、/etc 均为目录文件,ls -l 输出的第一个字符为 d。

验证命令:

  • file [目录路径]:直接标记为 directory;

  • stat [目录路径]:File type 字段为 directory,且 Links 数通常大于 2(目录默认包含 . 和 .. 两个隐藏链接)。


🌱 链接文件(l,软链接 / 硬链接)

链接文件分为软链接(符号链接,Symbolic Link)硬链接(Hard Link)

👉 软链接 ,类似 "快捷方式"

独立的文件,存储目标文件的路径,若目标文件删除,软链接会失效(显示 "broken link");

例如 ln -s /home/user/docs /tmp/docs_link 创建软链接;

验证命令:

  • file [软链接路径]:显示 symbolic link to [目标路径];

  • stat [软链接路径]:File type 为 symbolic link,且 Size 为目标路径的字符长度(非目标文件大小)。

实操示例:

复制代码
# 1. 先创建软链接:ln -s /etc/passwd /tmp/passwd_link
$ ln -s /etc/passwd /tmp/passwd_link

# 2. 验证软链接
$ file /tmp/passwd_link
/tmp/passwd_link: symbolic link to /etc/passwd # 明确为软链接,且显示目标路径

$ stat /tmp/passwd_link
  File: /tmp/passwd_link -> /etc/passwd # 箭头指向目标文件
  Size: 11 Blocks: 0 IO Block: 4096 symbolic link # File type 为 symbolic link
Device: tmpfs_inodefsd Inode: 1234 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 1000/ user) Gid: ( 1000/ user)
# 注:软链接权限为 lrwxrwxrwx(第一位 l),但实际权限由目标文件决定

👉 硬链接

与目标文件共享同一个 inode(文件的唯一标识),本质是 "同一个文件的多个名字",若目标文件删除,硬链接仍可访问文件内容,仅当所有硬链接都删除时,文件数据才会被释放。

验证命令:

  • file [硬链接路径]:显示结果与目标文件完全一致(无法直接识别为硬链接);

  • stat [硬链接路径]:Inode 编号与目标文件相同,Links 数比目标文件多 1(硬链接会增加 inode 的链接计数)。

实操示例:

复制代码
# 1. 先创建硬链接:ln /etc/passwd /tmp/passwd_hardlink
$ ln /etc/passwd /tmp/passwd_hardlink

# 2. 验证硬链接(file 无法区分,需对比 inode)
$ file /tmp/passwd_hardlink
/tmp/passwd_hardlink: ASCII text # 与目标文件 /etc/passwd 的 file 结果一致

# 3. 对比目标文件与硬链接的 inode
$ stat -c "%i %n" /etc/passwd /tmp/passwd_hardlink
131074 /etc/passwd # 目标文件 inode=131074
131074 /tmp/passwd_hardlink # 硬链接 inode 与目标完全相同

# 4. 查看链接数:目标文件的 Links 从 1 变为 2
$ stat /etc/passwd | grep Links
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)

🌱 设备文件(b /c,Block / Character Device)

用于与硬件设备交互的文件,分为块设备文件(b)字符设备文件(c)

👉 块设备文件(b)

用于存储设备(如硬盘、U 盘),以 "块" 为单位读写数据,支持随机访问;例如 /dev/sda1(硬盘分区)、/dev/mmcblk0(SD 卡);

👉 字符设备文件(c)

用于输入输出设备(如键盘、鼠标、打印机),以 "字符" 为单位顺序读写数据;例如 /dev/tty1(终端)、/dev/input/mouse0(鼠标)。


🌱 管道文件(p,Pipe)

用于进程间通信(IPC)的临时文件,分为匿名管道 (由 | 符号创建,如 ls | grep txt)和命名管道(由 mkfifo 命令创建,如 mkfifo my_pipe),数据写入管道后,被另一个进程读取后会立即删除。

匿名管道无实体路径,无法用 file/stat 直接查看,此处以 命名管道为例验证:

复制代码
# 1. 先创建命名管道:mkfifo /tmp/my_pipe
$ mkfifo /tmp/my_pipe

# 2. 验证命名管道
$ file /tmp/my_pipe
/tmp/my_pipe: fifo (named pipe)  # fifo 即命名管道

$ stat /tmp/my_pipe
  File: /tmp/my_pipe
  Size: 0           Blocks: 0          IO Block: 4096   fifo  # File type 为 fifo
Device: tmpfs_inodefsd  Inode: 5678     Links: 1
Access: (0644/prw-r--r--)  Uid: ( 1000/   user)   Gid: ( 1000/   user)
# 注:权限位第一位为 p(如 prw-r--r--),代表 pipe

🌱 套接字文件(s,Socket)

用于网络通信或本地进程间通信的文件,支持 TCP、UDP 等协议。

常见于 /var/run 目录(如 /var/run/mysqld/mysqld.sock,MySQL 服务的本地通信套接字)。

验证示例:

复制代码
# 验证 MySQL 本地套接字(若 MySQL 已启动)
$ file /var/run/mysqld/mysqld.sock
/var/run/mysqld/mysqld.sock: socket  # 直接识别为 socket

$ stat /var/run/mysqld/mysqld.sock
  File: /var/run/mysqld/mysqld.sock
  Size: 0           Blocks: 0          IO Block: 4096   socket  # File type 为 socket
Device: tmpfs_inodefsd  Inode: 7890     Links: 1
Access: (0660/srw-rw----)  Uid: (  112/   mysql)   Gid: (  118/   mysql)
# 注:权限位第一位为 s(如 srw-rw----),代表 socket

2.3 Linux 文件系统的工作流程

Linux 文件系统的工作流程涉及 "目录项(dentry) ""索引节点(inode) ""超级块(super block)" 三个核心概念。

它们共同协作实现文件的查找、读取与写入:

  • 超级块(Super Block)

    存储文件系统的 "元信息",如文件系统类型(Ext4、XFS)、总块数、空闲块数、inode 总数、挂载时间等,是文件系统的 "总览表"。

每个文件系统(如 /dev/sda1)都有一个超级块,通常备份在多个位置以防损坏。

  • 索引节点(inode)

    存储文件的 "属性信息",如文件大小、创建时间(ctime)、修改时间(mtime)、访问权限(rwx)、所属用户 / 组、数据块的位置(即文件数据在硬盘上的存储地址),每个文件对应唯一的 inode 编号(通过 ls -i 命令查看)。

    注意:inode 不存储文件名,文件名由目录文件管理。

  • 目录项(dentry)

    存储 "文件名与 inode 编号的映射关系",是目录文件的核心内容。

    例如,/home/user/docs 目录下有一个 report.pdf 文件,该目录的 dentry 会记录 report.pdf -> 12345(12345 为该文件的 inode 编号)。


📓 文件查找与读取流程

以 "用户执行 cat /home/user/docs/report.pdf 命令读取文件" 为例,Linux 系统的处理流程如下:

1️⃣ 解析路径

从根目录 / 开始,逐个解析路径中的目录(home → user → docs);

2️⃣ 查找目录项

  • 读取根目录的 inode(固定编号为 2,Linux 约定),通过 inode 找到根目录的数据块,从中获取 home 目录的 inode 编号;

  • 读取 home 目录的 inode,找到其数据块,获取 user 目录的 inode 编号;

  • 重复上述步骤,直到找到 docs 目录的 inode,进而在其数据块中找到 report.pdf 对应的 inode 编号(如 12345);

3️⃣ 验证权限

检查当前用户是否有读取 report.pdf 的权限(通过 inode 中的权限字段判断);

4️⃣ 读取文件数据

通过 report.pdf 的 inode 找到其数据块在硬盘上的存储地址,内核将数据块加载到内存,最终通过 cat 命令输出给用户。

这一流程的关键在于:文件名仅用于查找 inode,实际的文件属性与数据存储依赖 inode,因此即使文件名被修改,只要 inode 不变,文件数据也不会丢失。


2.4 常见的 Linux 文件系统类型

Linux 支持多种文件系统类型,不同类型适用于不同场景(如本地硬盘、U 盘、日志存储、网络共享),以下是最常用的几种:

1.Ext 系列(Ext2 / Ext3 / Ext4)

👉 Ext2(Second Extended Filesystem)

早期 Linux 主流文件系统,无日志功能,若突然断电可能导致数据损坏,适合小容量存储(如 U 盘);

👉 Ext3

在 Ext2 基础上增加 "日志功能(Journal)",先记录文件操作日志,再执行实际写入,降低断电数据损坏风险,兼容性好,但性能一般;

👉 Ext4(Fourth Extended Filesystem)

目前大多数 Linux 发行版(如 kylin v10)的默认本地文件系统,优化了 Ext3 的性能,支持:

  • 最大文件 size:16TB(理论支持 1EB);

  • 最大分区 size:1EB;

  • 延迟分配(Delayed Allocation):减少磁盘碎片;

  • 在线碎片整理(Online Defragmentation)

2.XFS

**特点:**高性能日志文件系统,由 SGI 开发,后被 Linux 接纳,kylin v10,CentOS 8、RHEL 8 已将其作为默认文件系统;

优势:

  • 支持超大容量:最大分区 size 18EB,最大文件 size 9EB,适合企业级存储(如数据库服务器、大数据集群);

  • 并行 I/O 性能优异:通过 "分配组(Allocation Group)" 将磁盘分区划分为多个独立区域,支持多线程并行读写;

  • 日志效率高:采用 "循环日志(Circular Log)",减少磁盘 I/O 开销。

3. Btrfs(B-tree Filesystem)

**特点:**被称为 "下一代 Linux 文件系统",设计目标是解决 Ext4 的局限性,支持 "写时复制(Copy-on-Write,CoW)" 技术;

核心功能:

  • 快照(Snapshot):快速创建文件系统快照,用于备份与版本控制;

  • RAID 支持:原生支持 RAID 0/1/10,无需依赖硬件 RAID;

  • 动态扩容 / 缩容:支持在线调整分区大小,无需卸载文件系统;

**现状:**目前在 Fedora、SUSE Linux 中应用较广,稳定性仍在持续优化,暂未成为主流发行版的默认选择。

其他常见类型

FAT32 / exFAT

适用于 U 盘、SD 卡等移动存储,兼容性好(支持 Windows、macOS、Linux),但 FAT32 最大支持 4GB 单个文件,exFAT 可突破此限制;

NTFS

Windows 默认文件系统,Linux 通过 ntfs-3g 驱动支持读写,适合跨系统共享硬盘;

NFS(Network File System)

网络文件系统,用于将远程服务器的目录挂载到本地,实现网络共享;

tmpfs

临时文件系统,数据存储在内存中,速度极快,/tmp 目录通常使用 tmpfs,系统重启后数据清空。

相关文档请见:

1.文件系统到底怎么玩?分区工具又该用哪个?

https://mp.weixin.qq.com/s/_H4ITNFPPhSE95ZS4LbHDw


3.从ext4文件系统到Linux文件树

当我们执行文件操作时,内核和硬件设备都在做些什么?

本章我们以ext4文件系统为例,来讲解Linux文件的底层实现原理。

1.ext4文件系统

磁盘一个大容量的存储设备,为了更高效地使用磁盘的存储空间,我们需要将磁盘划分成块(如4KB),块是磁盘存储数据的最小单位,Linux系统以块为单位来读写磁盘。

图1 ext4文件系统

ext4文件系统磁盘布局如图1所示。

当我们拿到一块新的磁盘时,我们并不能直接使用它,新的磁盘只有先分区和格式化才能使用**。**

分区是将物理磁盘划分为逻辑区域,格式化是为分区创建文件系统。

磁盘有了文件系统才能够被Linux系统识别,Linux系统才能正确访问磁盘文件。

磁盘分区+格式化的一个简单实战案例:

https://mp.weixin.qq.com/s/_SoX_9N5SH0L_yh8saRjtA

Linux系统中常见的文件系统有:ext4、XFS、Btrfs、ZFS、F2FS等。其中ext4文件系统使用最为广泛。

ext4文件系统将分区划分为多个**块组,**块组默认大小为128MB(包含32768个4KB块),块组结构如图2所示。

图2 ext4文件系统块组

块组各部分解析如下:

  • 超级块(Super Block):超级块存储了文件系统的关键参数,如块大小、inode数量、文件系统大小等元数据,对应数据结构为struct ext4_super_block。
  • 组描述符表(GDT):记录每个块组的使用情况,对应数据结构为struct ext4_group_desc。

  • 预留GDT块:预留空间,用于文件系统未来扩展。

  • inode位图:标记哪些inode已使用(1表示使用,0表示空闲)。

  • 数据位图:标记哪些数据块已使用(1表示使用,0表示空闲)。

  • inode表:存储所有struct ext4_inode结构,ext4_inode表示一个文件或目录。

  • 数据块:存储文件或目录内容的区域。

目录中的内容记录在块中,并通过HTree树来管理。文件的内容也同样记录在块中,并通过extents树来管理。限于篇幅,这部分内容本文不展开讲解。

2.Linux文件树

Linux系统以文件树来管理文件,在Linux用户眼中,文件树样式如图3所示。

图3 Linux用户眼中的文件树

Linux文件树是以根目录(/)为起点的单根树形目录结构,所有文件和子目录都从根目录延伸,形成一个层次化的文件系统组织。树形结构使得用户能够方便地浏览、查找和管理文件系统中的资源。同时,树形结构也很方便挂载新文件系统。

对于Linux内核来说,文件树由各种挂载实例(struct mount)组成,如图4所示。

在学习VFS(Virtual File System,虚拟文件系统)时,我们经常会围绕dentry(目录项)来理解Linux文件树。这种方式会让我们产生一个误解:Linux系统中所有的文件(相同或不同文件系统中的文件)都是通过dentry连接起来的。事实真是这样吗?接下来我们来揭晓答案。

struct mount结构体定义如下(简化版):

复制代码
struct mount {
    struct hlist_node mnt_hash;
    struct mount *mnt_parent;
    struct dentry *mnt_mountpoint;
    struct vfsmount mnt;
    union {
        struct rcu_head mnt_rcu;
        struct llist_node mnt_llist;
    };
    const char *mnt_devname;
    ......
};

关键字段解析如下:

  • mnt_hash:将struct mount实例链接到全局散列表mount_hashtable中,用于快速查找挂载点。

  • mnt_parent: 指向父挂载实例,形成挂载树的父子关系。

  • mnt_mountpoint:指向挂载点的目录项(dentry),表示该挂载实例的挂载位置。

  • mnt:嵌入的vfsmount结构体实例,struct vsfmount结构体定义如下:

    struct vfsmount {
    struct dentry *mnt_root;
    struct super_block *mnt_sb;
    int mnt_flags;
    struct mnt_idmap *mnt_idmap;
    };

  • mnt_root:指向挂载文件系统的根目录项(dentry),是访问整个文件系统的起点。当用户访问挂载点时,内核通过此指针定位到文件系统的根目录。

  • mnt_sb:指向文件系统的超级块(如ext4),包含文件系统的元数据信息。

  • mnt_devname:存储设备名称 (如/dev/sda1),标识挂载的物理设备。

从图4可知,Linux系统中每个挂载实例都是独立的,每个挂载实例内部都有一个私有文件树(内部文件树),挂载实例的mnt_mountpoint成员为私有文件树的根目录(dentry)。

挂载实例之间呈父子关系,Linux系统根目录(/)所处的挂载实例为祖先挂载实例,挂载实例之间通过挂载点(父挂载实例中的一个目录(dentry))连接。

注意:各个挂载实例的私有文件树并没有直接通过dentry关联,私有文件树通过挂载实例和挂载点间接关联。

私有文件树由dentry构成,struct dentry结构体定义如下(简化版):

复制代码
struct dentry {
    struct hlist_bl_node d_hash;
    struct dentry *d_parent;
    struct qstr d_name;
    struct inode *d_inode;
    const struct dentry_operations *d_op;
    struct super_block *d_sb;
    struct list_head d_child;
    struct list_head d_subdirs;
    ......
};
  • d_hash:哈希表节点,用于快速查找目录项,加速路径解析。
  • d_parent:指向父目录的目录项,形成文件系统层次结构。
  • d_name:存储目录项名称(文件名或目录名)。
  • d_inode:指向关联的inode,表示该目录项对应的文件或目录,``NULL``表示负目录项(不存在的文件)。
  • d_op:指向目录项操作函数表。
  • d_sb:指向文件系统超级块。
  • d_child:同父目录下的兄弟节点链表。
  • d_subdirs:子目录链表,指向该目录下的所有子目录。

通过d_parent和d_subdirs成员就能够构建文件系统树形结构。

为了方便查找挂载实例,Linux系统会通过挂载点文件路径和挂载实例计算哈希值,再将挂载实例插入全局挂载哈希表(mount_hashtable)。

3.挂载ext4文件系统

挂载是指将硬件设备的文件系统和Linux系统中的文件系统,通过指定目录(挂载点)进行关联

Linux挂载文件系统过程如图5所示,我们可以用一句话来概括Linux挂载操作:内核创建并初始化一个新挂载实例,并将新挂载实例关联父挂载实例。

用户程序执行挂载命令(mount)后,内核需要根据mount命令传入的设备文件名(如/dev/sda1)打开块设备,并读取ext4文件系统超级块(struct ext4_super_block),为了兼容VFS,内核需要创建一个struct super_block对象并包含ext4超级块。同时,内核也会打开ext4文件系统根目录,作为私有文件树的根目录。

接着,内核开始执行挂载操作,内核会创建一个新挂载实例并初始化,初始化工作主要包括:

  • 设置超级块:新挂载实例mnt_sb成员指向super_block对象,挂载实例和超级块进行绑定。
  • 设置根目录:读取ext4文件系统根目录信息,创建dentry和inode,dentry关联inode并记录在新挂载实例mnt_root成员。
  • 设置父挂载实例:新挂载实例mnt_parent指向父挂载实例,二者呈父子关系。
  • 设置挂载点:新挂载实例mnt_mountpoint指向挂载点dentry,新挂载实例和挂载点进行绑定。
  • 新挂载实例插入挂载哈希表:通过挂载点文件路径和挂载实例计算哈希值,将新挂载实例插入哈希表。

完成上述工作后,ext4文件系统就成功挂载至Linux文件树了。注意,ext4文件系统文件树并没有直接关联Linux文件树。当我们需要访问ext4文件系统时,先要查找挂载哈希表找到挂载实例,再基于挂载实例根目录访问文件系统。

4. 文件路径解析

文件系统挂载至Linux文件树后,我们就能够通过Linux文件树访问文件系统中的文件了。前面做的所有工作,就是为了我们能够顺利地访问文件系统中的文件。

图6 Linux打开文件过程

访问文件需要进行文件路径解析,我们以打开文件为例来讲解该过程,如图6所示。

用户程序调用open函数创建和打开文件时,需要传入文件路径,文件路径就像一个地图,能够帮助我们在复杂的文件树中找到目的文件。

文件路径可以是绝对路径相对路径,二者的区别在于文件路径解析的起点(dentry)不一样。

内核解析文件路径时,需要借助struct path结构动态记录当前目录的dentry以及其所处的挂载实例。每解析一层目录都会更新一次path。解析过程中如果碰到挂载点,需要根据挂载点文件路径计算哈希值查找挂载哈希表获取子挂载实例,path结构的mnt成员更新为子挂载实例,dentry成员更新为子挂载实例mnt_root成员(根目录dentry)。更新完后,从新挂载实例根目录继续解析文件路径。

当解析至目标文件(文件或目录)的父目录dentry后,文件路径解析工作基本就完成了。创建和打开文件的工作将由父目录的inode完成。内核会查询父目录是否存在目标文件(test.txt)。如果目标文件已经存在,则不会创建文件;否则,内核会创建并打开目标文件,创建和打开文件可以理解为:创建一个新的dentry和inode,dentry关联inode并插入文件树。当然,内核需要将这些信息同步至ext4文件系统,保持二者之间信息对称。

完成上述工作,用户程序还不能读写文件,用户程序读写文件需要用到文件描述符(fd)。内核会创建一个struct file对象,并将inode中的关键信息复制到file对象。然后申请一个未使用的fd,新fd关联file对象并记录在进程已打开文件表。最后,内核返回fd给用户程序,用户程序通过fd就能读写文件了。

总结:

Linux一切皆文件,Linux文件系统架构非常复杂,希望本文能够帮助你进一步了解Linux文件。

相关推荐
胡萝卜3.02 小时前
Makefile 实战指南:从零到一掌握自动化构建
运维·机器学习·自动化·c++开发·makfile·gmu make
FIT2CLOUD飞致云2 小时前
汇报丨1Panel开源面板2025年终总结
linux·运维·服务器·开源·github·1panel
小李独爱秋2 小时前
计算机网络经典问题透视:拒绝服务(DoS)与分布式拒绝服务(DDoS)攻击全景解析
运维·服务器·分布式·计算机网络·ddos
无敌糖果2 小时前
使用Nginx二级代理Jumpserver堡垒机
运维·nginx
真正的醒悟2 小时前
20251231-思维格局
运维
code tsunami2 小时前
DrissionPage 与 CapSolver:打造无痕、高效的自动化爬虫利器
运维·爬虫·自动化
xiaoliuliu123452 小时前
libicu-62.1-6.ky10.x86_64.rpm 安装步骤详解(麒麟V10系统)
linux·服务器·centos
怪力左手2 小时前
LSP、DAP语言服务器
运维·服务器·里氏替换原则
FreeBuf_2 小时前
欧洲航天局确认外部服务器遭入侵
服务器·安全·php