Linux的文件系统(3)——系统挂载与目录结构

文件系统是在一个磁盘(硬盘、光盘及其它存储设备)上的目录结构,一个磁盘设备可以包含一个或多个文件系统

不同的Linux发型版本的文件系统结构不尽相同,本文基于CentOS

硬盘驱动到文件系统挂载

硬盘中的内容只有挂载后才能使用。Windows是自动挂载,Unix类的操作系统是通过 mount 命令实现,挂载时要有挂载点,通常是一个空置的目录。常见的命令如下:

$ mount /dev/fd0 /media/floppy

挂载点是一个空目录,(若不存在,需要先建立一个空目录),mount 后该目录中的内容就是你载入的文件系统的内容

为什么需要文件系统的挂载,需要我们先理解Linux系统的管理结构——从硬盘到文件系统

  1. 硬盘驱动(Device Driver)

    文件内容是存储在硬盘上面的

    常见的硬盘类型有PAT、 SATA和SCSI等,在Linux系统中,对不同硬盘所提供的驱动模块一般都存放在内核目录树 drivers/ata 中。更通用的硬盘驱动,也许会直接被编译到内核中,而不会以模块的方式出现,可以通过查看 /boot/config-xxx.xxx 文件来确认

  2. General Block Device Layer

    不同的硬盘驱动,会应用不同的IO接口,内核认为这种杂乱的接口,不利于管理。于是把这些接口抽象一下,形成一个统一的对外接口,即 General Block Device Layer ,隐藏硬件细节,为上层程序提供统一接口

  3. 文件系统

    文件系统这一层大家最熟悉了,常见的文件系统包括 FAT32、NTFS (Windows)、ext2、ext3 (Linux)等,目前Linux发行版本默认使用的文件系统包括ext4、XFS等。系统通过文件系统才能识别硬盘

  4. 虚拟文件系统(Virtual File System,VFS)

    不同的文件系统又都有着各自不同的实现细节,而用户想要的是,不管你是什么实现,他们只关心相同的读取/写入/修改/删除等文件操作

    所以,VFS就把这些不同的文件系统做一个抽象,提供统一的API访问接口。这些统一的API,再经过 System Call 包装一下,用户便可以在 User Space 的层面通过系统调用来操作不同的文件了

    VFS所提供的常用API有:mount(), umount() 、open(),close() …,到了这步,通过文件挂载,我们才真正的可以在用户空间的层面操作文件了

上面的结构中,硬盘驱动,文件系统,虚拟文件系统,以及系统调用,都属于内核空间,换言之,这些不同层次的实现,都是由内核来做的。而所谓用户空间的操作,也就是一些对磁盘的读写访问操作

Linux的默认文件系统结构——一级目录

Linux 所有文件系统都安装在一个树根上。进行分区时必须先划分一个根分区,然后将其它的分区都挂载到这个根目录下

Linux启动时,第一个必须挂载的也必须是根文件系统;若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动。之后可以自动或手动挂载其他的文件系统(因此,一个系统中可以同时存在不同的文件系统)

自动挂载的系统存于 /etc/fstab 中,这是一个纯文本文件,开机后,系统自动搜索文件中的内容进行挂载

一个fstab文件实例:

# This file is edited by fstab-sync– see 'man fstab-sync' for details
LABEL=/1 / ext3 defaults 1 1
none /dev/pts devpts gid=5,mode=620 0 0
none /dev/shm tmpfs defaults 0 0
LABEL=/home1 /home ext3 defaults 1 2
none /proc proc defaults 0 0
none /sys sysfs defaults 0 0
LABEL=SWAP swap swap defaults 0 0
#
/dev/hda2 /winnt ntfs noauto,nls=cp936,ro,users 0 0
/dev/hda5 /dosd ntfs noauto,nls=cp936,ro,users 0 0
/dev/hda6 /dose vfat noauto,iocharset=cp936,rw 0 0
/dev/sda1 /usb1 vfat noauto,iocharset=cp936,rw 0 0

从左到右参数依次是设备名、挂载点、文件系统类型、操作选项、dump时是否记录、fsck时的顺序

启动后,常见的Linux文件系统结构如下:

FHS规定的Linux一级目录及功能
一级目录 功能(作用)
/bin/ 存放系统命令,普通用户和 root 都可以执行。放在 /bin 下的命令在单用户模式下也可以执行
/boot/ 系统启动目录,保存与系统启动相关的文件,如内核文件和启动引导程序(grub)文件等
/dev/ 设备文件保存位置
/etc/ 配置文件保存位置。系统内所有采用默认安装方式(rpm 安装)的服务配置文件全部保存在此目录中,如用户信息、服务的启动脚本、常用服务的配置文件等
/home/ 普通用户的主目录(也称为家目录)。在创建用户时,每个用户要有一个默认登录和保存自己数据的位置,就是用户的主目录,所有普通用户的主目录是在 /home/ 下建立一个和用户名相同的目录。如用户 liming 的主目录就是 /home/liming
/lib/ 系统调用的函数库保存位置
/media/ 挂载目录。系统建议用来挂载媒体设备,如软盘和光盘(一些图形界面的Linux系统会自动将插入的光盘挂载到这一目录下)
/mnt/ 挂载目录。早期 Linux 中只有这一个挂载目录,并没有细分。系统建议这个目录用来挂载额外的设备,如 U 盘、移动硬盘和其他操作系统的分区
/misc/ 挂载目录。系统建议用来挂载 NFS 服务的共享目录。虽然系统准备了三个默认挂载目录 /media/、/mnt/、/misc/,但是到底在哪个目录中挂载什么设备可以由管理员自己决定。例如,笔者在接触 Linux 的时候,默认挂载目录只有 /mnt/,所以养成了在 /mnt/ 下建立不同目录挂载不同设备的习惯,如 /mnt/cdrom/ 挂载光盘、/mnt/usb/ 挂载 U 盘,都是可以的
/opt/ 第三方安装的软件保存位置。这个目录是放置和安装其他软件的位置,手工安装的源码包软件都可以安装到这个目录中。不过笔者还是习惯把软件放到 /usr/local/ 目录中,也就是说,/usr/local/ 目录也可以用来安装软件
/root/ root 的主目录。普通用户主目录在 /home/ 下,root 主目录直接在“/”下
/sbin/ 保存与系统环境设置相关的命令,只有 root 可以使用这些命令进行系统环境设置,但也有些命令可以允许普通用户查看
/srv/ 服务数据目录。一些系统服务启动之后,可以在这个目录中保存所需要的数据
/run/ 存放运行时系统信息,比如当前系统信息、当前用户信息和后台驻留程序数据、PID等。一般该目录下内容会在启动时被更新(FHS 3.0新标准)
/tmp/ 临时目录。系统存放临时文件的目录,在该目录下,所有用户都可以访问和写入。建议此目录中不能保存重要数据,最好每次开机都把该目录清空

以上的文件结构被称为 FHS 标准,即 Filesystem Hierarchy Standard,于1994年由Linux基金会首次发布,目前已经更新到第三版(2015年发布)

该标准规定了 Linux 系统中所有一级目录以及部分二级目录(/usr 和 /var)的用途。发布此标准的主要目的就是为了让用户清楚地了解每个目录应该存放什么类型的文件。毕竟Linux作为开源系统,发行版本很多,利用 Linux 开发产品的团队也有很多,如果任由每个人都按照自己的想法来配置 Linux 系统文件目录,后期可能会产生诸多的管理问题。

试想,如果你进入一家公司,所用 Linux 系统的文件目录结构与所学的完全不同,实在令人头疼

绝大多数 Linux 发行版系统都遵循 FHS 标准(个别的比如GoboLinux、 NixOS不遵循此标准)

除了FHS规定,Linux 系统根目录下通常还包含下面几个一级目录:

其他一级目录及功能
一级目录 功能(作用)
/lost+found/ 当系统意外崩溃或意外关机时,产生的一些文件碎片会存放在这里。在系统启动的过程中,fsck 工具会检查这里,并修复已经损坏的文件系统。这个目录只在每个分区中出现,例如,/lost+found 就是根分区的备份恢复目录,/boot/lost+found 就是 /boot 分区的备份恢复目录
/proc/ 虚拟文件系统。该目录中的数据并不保存在硬盘上,而是保存到内存中。主要保存系统的内核、进程、外部设备状态和网络状态等。如 /proc/cpuinfo 是保存 CPU 信息的,/proc/devices 是保存设备驱动的列表的,/proc/filesystems 是保存文件系统列表的,/proc/net 是保存网络协议信息的......
/sys/ 虚拟文件系统。和 /proc/ 目录相似,该目录中的数据都保存在内存中,主要保存与内核相关的信息

Linux的默认文件系统结构——二级目录

除了一级目录,Linux文件系统下还有两个重要的二级目录,FHS也做了相关规定

/usr 目录

usr(注意不是 user),全称为 Unix Software Resource,此目录用于存储系统软件资源。FHS 建议所有开发者,应把软件产品的数据合理的放置在 /usr 目录下的各子目录中,而不是为他们的产品创建单独的目录

Linux 系统中,所有系统默认的软件都存储在 /usr 目录下,/usr 目录类似 Windows 系统中 C:\Windows\ + C:\Program files\ 两个目录的综合体

FHS 建议,/usr 目录应具备如下所示的子目录:

/usr 子目录及功能
子目录 功能(作用)
/usr/bin/ 存放系统命令,普通用户和超级用户都可以执行。这些命令和系统启动无关,在单用户模式下不能执行
/usr/sbin/ 存放根文件系统不必要的系统管理命令,如多数服务程序,只有 root 可以使用。
/usr/lib/ 应用程序调用的函数库保存位置
/usr/XllR6/ 图形界面系统保存位置
/usr/local/ 手工安装的软件保存位置。我们一般建议源码包软件安装在这个位置
/usr/share/ 应用程序的资源文件保存位置,如帮助文档、说明文档和字体目录
/usr/src/ 源码包保存位置。我们手工下载的源码包和内核源码包都可以保存到这里。不过笔者更习惯把手工下载的源码包保存到 /usr/local/src/ 目录中,把内核源码保存到 /usr/src/linux/ 目录中
/usr/include C/C++ 等编程语言头文件的放置目录

很多Linux发行版本中,根目录下的/bin/、/sbin/、/lib/都实际为指向/usr/bin/、/usr/sbin/、/usr/lib/的软链接(比如CentOS)。更极端的系统可能将/sbin/、/usr/sbin/也统一到/usr/bin/

/var 目录

/var 目录用于存储动态数据,例如缓存、日志文件、软件运行过程中产生的文件等。通常,此目录下建议包含如下表所示的子目录:

/var子目录及功能
子目录 功能(作用)
/var/lib/ 程序运行中需要调用或改变的数据保存位置。如 MySQL 的数据库保存在 /var/lib/mysql/ 目录中
/var/log/ 登陆文件放置的目录,其中所包含比较重要的文件如 /var/log/messages, /var/log/wtmp 等
/var/run/ 存放运行时系统信息,比如一些服务和程序运行后,它们的 PID(进程 ID)等,FHS 3.0版本后,该位置被改为直接存放在根目录下的/run/
/var/spool/ 里面主要都是一些临时存放,随时会被用户所调用的数据,例如 /var/spool/mail/ 存放新收到的邮件,/var/spool/cron/ 存放系统定时任务。
/var/www/ RPM 包安装的 Apache 的网页主目录
/var/nis和/var/yp NIS 服务机制所使用的目录,nis 主要记录所有网络中每一个 client 的连接信息;yp 是 linux 的 nis 服务的日志文件存放的目录
/var/tmp 一些应用程序在安装或执行时,需要在重启后使用的某些文件,此目录能将该类文件暂时存放起来,完成后再行删除

日常使用中,如果是临时文件一般优先使用用户的主目录或 /tmp/ 目录,要小心 Linux 下有些目录中不能直接修改和保存数据,比如 /proc//sys/ 目录,因为它们是保存在内存中的,如果在这里写入数据,那么你的内存会越来越小,直至死机;又比如 /boot/ 目录,也不能保存额外数据,因为 /boot/ 目录会单独分区作为启动分区,如果没有空闲空间,会导致系统不能正常启动

最后用一张图来描述 FHS 3.0 下的 Linux 默认文件系统结构及之间的关系大概如下图(来源于《鸟哥的Linux私房菜》):

MacOS下的默认文件结构

虽然学习的都是Linux,但实际开发中本地机使用的是Mac。MacOs基于BSD系统实现,所以也是Like-Unix系统,遵循FHS标准。但与Linux又有一些不同的地方

MacOS的默认目录及功能
目录 功能(作用)
/Applications/ 应用程序目录,默认所有的GUI应用程序都安装在这里
/System/ 系统文件目录,类似与Windows的C:\windows32,该文件夹下/System/Library/存放了系统调用库,/System/Applications/存放了系统自带的GUI程序,/System/iOSSupport/则提供了系统的iOS支持
/Library/ 应用程序的函数调用库,包括了大部分非核心的系统组件,类似于Linux的/lib/
/Users/ 普通用户的主目录,类似于Linux的/home/
/Volumes/ 文件系统挂载点存放目录,类似与Linux的/mnt/
/bin/ 传统Unix系统命令的存放目录,与Linux类似
/cores/ 内核转储文件存放目录。当一个进程崩溃时,如果系统允许则会产生转储文件,大致类似于Linux的/lost+found/
/dev/ 设备文件保存目录,与Linux类似
/etc/ 传统Unix系统配置文件存放目录。此目录实际为指向/private/etc的软链接
/home/ 空文件夹,存在是为了与Linux或其他Unix系统兼容
/opt/ 第三方安装的软件保存目录,与Linux类似。在MacOS中,通过homebrew安装的软件存放在/opt/homebrew-cask/目录下
/sbin/ 保存与系统环境设置相关的命令,与Linux类似
/tmp/ 临时文件存放目录,其权限为所有人任意读写。此目录实际为指向/private/tmp的软链接
/private/ 存放实际的/etc/、/tmp/、/var/文件内容
/usr/及子目录 存放第三方安装的软件,与Linux类似
/var/及子目录 存放经常变化的文件,如日志文件。此目录实际为指向/private/var的软链接

上表中的目录只有/Applications//Library//System//Users/是对用户默认可见的,其他目录均是对用户默认隐藏的

可以看到MacOS保留了Unix传统的文件结构与基础内容(维持着FHS标准与POSIX兼容),同时将更属于MacOS的核心部分存储在新的目录结构下

MacOS将/etc/、/tmp/、/var/三处实际存储在/private/目录下,并用软连接指向,似乎是传承自NeXTStep系统的文件结构,适用于早期内存较小又希望通过网络启动的计算机(这样只需要把启动盘挂载到/private/下就可以访问必要的数据文件了)。NeXTStep正是早期的MacOS的雏形

由于软件类型的不同,Mac下的软件(包括系统自带软件、命令程序)有可能安装在:

  • /System/Applications/中:系统自带的GUI应用程序,如相册、邮箱
  • /Applications/中:使用App Store安装的GUI应用程序
  • /usr/bin/中:系统自带的第三方程序,如系统自带的python
  • /usr/local/bin/中:使用命令行安装的第三方程序(按照Linux标准规范)。使用homebrew安装的程序也会在这里建立一个软连接
  • /usr/local/Cellar/ 或 /opt/homebrew/Cellar/中:使用homebrew安装的第三方程序
  • /opt/homebrew-cask/Caskroom/中:使用homebrew-cask安装的第三方GUI程序
  • /Users/username/Applications/中:使用homebrew-cask安装的程序会在这里建立一个软链接

由于MacOS不自带包管理工具,所以常用homebrew来实现包管理。homebrew自身位于 /usr/local/Homebrew目录,而使用其安装的软件包则在/usr/local/Cellar/中

cask是homebrew的一个扩展,让homebrew也可以安装许多MacOS的GUI软件,使用的安装目录是/opt/homebrew-cask/Caskroom/

使用homebrew-cask安装的GUI软件会在/Users/username/Applications/目录下建立一个指向自身的软链接

使用homebrew安装的GUI软件会在/usr/local/bin/目录下建立一个指向自身的软链接

对应的,调用的函数库则在:

  • /System/Library/中:系统的核心调用函数库
  • /Library/中:系统的非核心调用函数库或使用App Store安装的软件调用函数库
  • /Users/username/Library/中:用户个人账户中的一些支持库文件
  • /usr/local/lib/中:使用命令行安装程序的调用函数库,并按照Linux标准规范
  • /usr/lib/中:系统自带程序的调用函数库,如系统自带的python

参考&扩展

Linux文件目录结构一览表
FreeBSD 使用手册-目录架构
鸟哥的Linux私房菜-认识Linux文件系统
技术摘要| Mac OS 与 Linux 的目录结构比较