admin管理员组

文章数量:1558042

文章目录

  • 1. 前言
  • 2. 文件
    • 2.1. 一切皆文件
    • 2.2. 文件属性
    • 2.3. 目录结构
    • 2.4. 文件路径
  • 3. 文件系统
    • 3.1. 文件系统种类
    • 3.2. 文件系统特性
      • 3.2.1. 格式化
      • 3.2.2. 格式
    • 3.3. EXT 族文件系统
      • 3.3.1. EXT2 文件系统
        • 3.3.1.1. data block(数据区块)
        • 3.3.1.2. inode table(节点表)
        • 3.3.1.3. inode bitmap(节点位图)
        • 3.3.1.4. block bitmap(区块位图)
        • 3.3.1.5. filesystem description(文件系统描述说明)
        • 3.3.1.6. superblock(超级区块)
      • 3.3.2. 与目录树的关系
        • 3.3.2.1. 目录
        • 3.3.2.2. 文件
        • 3.3.2.3. 目录树读取
      • 3.3.3. EXT3/4 文件系统
        • 3.3.3.1. 文件的存取
        • 3.3.3.2. 数据不一致状态
        • 3.3.3.3. 日志式文件系统
    • 3.4. 挂载点的意义
    • 3.5. 虚拟文件系统
    • 3.6. 文件系统简单操作
      • 3.6.1. 磁盘与目录的容量
        • 3.6.1.1. df
        • 3.6.1.2. du
      • 3.6.2. 实体链接与符号链接
        • 3.6.2.1. ln
        • 3.6.2.2. 实体链接(hard link)
        • 3.6.2.3. 符号链接(symbolic link)
      • 3.6.3. 文件系统信息
        • 3.6.3.1. 查看文件系统类型
        • 3.6.3.2. superblock 信息
          • 3.6.3.2.1. dumpe2fs
  • 4. 文件系统管理
    • 4.1. 磁盘分区
      • 4.1.1. 设备文件名
        • 4.1.1.1. 磁盘命名
        • 4.1.1.2. 分区命名
      • 4.1.2. 分区挂载
      • 4.1.3. 分区状态
        • 4.1.3.1. lsblk 列出磁盘列表
        • 4.1.3.2. blkid 列出装置的 UUID
        • 4.1.3.3. parted 列出磁盘分区信息
      • 4.1.4. 分区制作
        • 4.1.4.1. fdisk
        • 4.1.4.2. /proc/partitions
        • 4.1.4.3. partprobe
    • 4.2. 磁盘格式化
      • 4.2.1. mkfs
      • 4.2.2. mkfs.ext4
    • 4.3. 文件系统检测
      • 4.3.1. fsck
      • 4.3.2. fsck.ext4
    • 4.4. 文件系统挂载
      • 4.4.1. mount
        • 4.4.1.1. 挂载不指定类型
        • 4.4.1.2. 重新挂载根目录
        • 4.4.1.3. 挂载不特定目录
        • 4.4.1.4. 设置开机挂载
          • 4.4.1.4.1. /etc/fstab
          • 4.4.1.4.2. /etc/mtab
        • 4.4.1.5. 特殊LOOP设备挂载
          • 4.4.1.5.1. 挂载光盘/DVD镜像文件
          • 4.4.1.5.2. 挂载大文件
            • 4.4.1.5.2.1. 建立大型文件
            • 4.4.1.5.2.2. 格式化大型文件
            • 4.4.1.5.2.3. 挂载大型文件
            • 4.4.1.5.2.4. 卸载大型文件
      • 4.4.2. umount
    • 4.5. 磁盘/文件系统参数修订
      • 4.5.1. mknod
      • 4.5.2. tune2fs
    • 4.6. 内存置换空间
      • 4.6.1. 使用实体分区槽创建swap
      • 4.6.2. 使用文件创建swap
  • 5. 文件系统原理
  • 6. 参考

1. 前言

本文将从文件、文件系统、文件系统管理、文件原理几个方面由浅入深地介绍 Linux 的文件系统。

2. 文件

2.1. 一切皆文件

“一切皆是文件” 是 Unix/Linux 的基本哲学之一。

这句话中的 “文件” 不仅仅是指我们通常所说的文件,而是指 Linux 世界中的所有、任意、一切东西都可以通过文件的方式访问和管理。它是一个抽象的概念,这才符合哲学意味。

linux 中有 7 种文件类型:普通文件、目录文件、块设备文件、字符设备、套接字文件、管道文件、链接文件。

这些文件都可以用一套相同的API(如:open/read/write/close等)进行操作。

这正好又符合 Unix/Linux 的另一个哲学思想“简单原则”,即著名的 KISS(keep it simple, stupid),意思是“保持简单和笨拙”。

2.2. 文件属性

Linux下的文件除了文件内容本身,还有一些必要的属性信息。如下图所示:

2533274790421609 drwxrwxrwx 1 canpool canpool 4.0K Jun 6 23:53 projects

  • 索引节点编号:2533274790421609
  • 文件类型:文件类型是 ‘d’,表示这是一个目录文件
  • 文件权限:rwxrwxrwx 表示文件可读、可写、可执行,文件所归属的用户组可读可执行,其它用户可读可写可执行
  • 硬链接个数:表示projects这个目录没有其它的硬链接,因为连接数是1,就是它本身
  • 文件属主:表示这个目录所属的用户,这里表示projects目录被canpool用户拥有(第一个canpool)
  • 文件属组:表示这个目录所属的用户组,这里表示projects目录属于canpool用户组(第二个canpool)
  • 文件大小:目录大小是4K字节
  • 文件修改时间:这里的时间是该目录最后被更新(包括文件创建、内容更新、文件名更新等)的时间。可用命令 stat 查看文件的修改、访问、创建时间。
canpool@DESKTOP-ODCM7SC:~/projects/canpool/shcanpool$ stat projects/
  File: projects/
  Size: 4096            Blocks: 0          IO Block: 4096   directory
Device: fh/15d  Inode: 2533274790421609  Links: 1
Access: (0777/drwxrwxrwx)  Uid: ( 1000/ canpool)   Gid: ( 1000/ canpool)
Access: 2022-06-06 23:53:17.886556500 +0800
Modify: 2022-06-06 23:53:17.885560400 +0800
Change: 2022-06-06 23:53:17.885560400 +0800
 Birth: -

备注:细心的读者可能会发现目录大小都是 4K,实际上这只是凑巧,但目录大小基本上都是 block 大小的倍数,下文会介绍。

2.3. 目录结构

由于“Linux 一切皆文件”,那么用户在使用 Linux 的过程中,就难免要跟各种文件打交道。如果 Linux 中的各种库、头文件、命令、配置文件等都自由放置的话,那么这将是灾难性的,将会给应用和管理造成诸多困扰。于是 FHS(Filesystem Hierarchy Standard,文件系统层次标准)就应运而生了,下面是遵循 FHS 标准的大致模样。

canpool@DESKTOP-ODCM7SC:~/projects/canpool/shcanpool$ ls /
bin   dev  home  lib    lib64   media  opt   root  sbin  srv  tmp  var
boot  etc  init  lib32  libx32  mnt    proc  run   snap  sys  usr

FHS 标准使得众多的Linux发布包有了可以遵循的标准,使得软件和用户可以预测已经安装了的文件和目录的位置。它定义了如下的内容:

  • 定义了文件系统中每个区域的用途
  • 定义了所需要的最小构成的文件和目录
  • 给出了例外处理和矛盾的特殊例子

FHS 实际上仅是规范在根目录(/)下面各个主要目录应该放什么样的文件。FHS定义了两层规范:

  • 第一层:/ 下面的各个目录应该要放什么文件数据,例如 /etc 应该要放置配置文件,/bin 与 /sbin 则应该要放置可执行文件等。
  • 第二层:则是针对 /usr 及 /var 这两个目录的子目录来定义。例如 /var/log 放置系统登录文件、/usr/share 放置共享数据等。

由于 FHS 仅是定义出最上层(/)及子层(/usr, /var)的目录内容应该要放置的文件数据,因此,在其他子目录层级内,就可以随开发人员自行配置了。

下面是对一些必要目录的介绍:

目录介绍
/binbin 是 Binaries (二进制文件) 的缩写, 这个目录存放着最经常使用的命令。
/boot这里存放的是启动 Linux 时使用的一些核心文件,包括一些连接文件以及镜像文件。
/devdev 是 Device(设备) 的缩写, 该目录下存放的是 Linux 的外部设备,在 Linux 中访问设备的方式和访问文件的方式是相同的。
/etcetc 是 Etcetera(等等) 的缩写,这个目录用来存放所有的系统管理所需要的配置文件和子目录。
/home用户的主目录,在 Linux 中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的,如上图中的 alice、bob 和 eve。
/liblib 是 Library(库) 的缩写这个目录里存放着系统最基本的动态连接共享库,其作用类似于 Windows 里的 DLL 文件。几乎所有的应用程序都需要用到这些共享库。
/lost+found这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。
/medialinux 系统会自动识别一些设备,例如U盘、光驱等等,当识别后,Linux 会把识别的设备挂载到这个目录下。
/mnt系统提供该目录是为了让用户临时挂载别的文件系统的,我们可以将光驱挂载在 /mnt/ 上,然后进入该目录就可以查看光驱里的内容了。
/optopt 是 optional(可选) 的缩写,这是给主机额外安装软件所摆放的目录。比如你安装一个ORACLE数据库则就可以放到这个目录下。默认是空的。
/procproc 是 Processes(进程) 的缩写,/proc 是一种伪文件系统(也即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件,这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件,比如可以通过下面的命令来屏蔽主机的ping命令,使别人无法ping你的机器:echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
/root该目录为系统管理员,也称作超级权限者的用户主目录。
/sbins 就是 Super User 的意思,是 Superuser Binaries (超级用户的二进制文件) 的缩写,这里存放的是系统管理员使用的系统管理程序。
/selinux这个目录是 Redhat/CentOS 所特有的目录,Selinux 是一个安全机制,类似于 windows 的防火墙,但是这套机制比较复杂,这个目录就是存放selinux相关的文件的。
/srv该目录存放一些服务启动之后需要提取的数据。
/sys这是 Linux2.6 内核的一个很大的变化。该目录下安装了 2.6 内核中新出现的一个文件系统 sysfs 。sysfs 文件系统集成了下面3种文件系统的信息:针对进程信息的 proc 文件系统、针对设备的 devfs 文件系统以及针对伪终端的 devpts 文件系统。该文件系统是内核设备树的一个直观反映。当一个内核对象被创建的时候,对应的文件和目录也在内核对象子系统中被创建。
/tmptmp 是 temporary(临时) 的缩写这个目录是用来存放一些临时文件的。
/usrusr 是 unix shared resources(共享资源) 的缩写,这是一个非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似于 windows 下的 program files 目录。
/usr/bin系统用户使用的应用程序。
/usr/sbin超级用户使用的比较高级的管理程序和系统守护程序。
/usr/src内核源代码默认的放置目录。
/varvar 是 variable(变量) 的缩写,这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。
/run是一个临时文件系统,存储系统启动以来的信息。当系统重启时,这个目录下的文件应该被删掉或清除。如果你的系统上有 /var/run 目录,应该让它指向 run。

2.4. 文件路径

文件名路径分为绝对路径和相对路径两种:

  • 绝对路径:由根目录(/)开始写起的文件名或目录名称,例如:/home/canpool/.bashrc
  • 相对路径:相对于当前路径的文件名写法。例如:./home/canpool 或 …/…/home/canpool/ 等等。

路径在文件系统中是一个很关键的索引,标识着文件所在的位置,文件的底层操作也要依赖它的路径。

3. 文件系统

Linux 中的文件属性和内容,实际上是通过文件系统进行管理的。

3.1. 文件系统种类

Linux 内核源码目录 fs 下存在几十种文件系统,如下是 linux-5.13.5 下的文件系统介绍:

9p          configfs  ext2      hugetlbfs   nfsd        qnx4      ufs
adfs        cramfs    ext4      iomap       nilfs2      qnx6      unicode
affs        crypto    f2fs      isofs       nls         quota     vboxsf
afs         debugfs   fat       jbd2        notify      ramfs     verity
autofs      devpts    freevxfs  jffs2       ntfs        reiserfs  xfs
befs        dlm       fscache   jfs         ocfs2       romfs     zonefs
bfs         ecryptfs  fuse      kernfs      omfs        squashfs  zzzz
btrfs       efivarfs  gfs2      lockd       openpromfs  sysfs
cachefiles  efs       hfs       minix       orangefs    sysv
ceph        erofs     hfsplus   netfs       overlayfs   tracefs
cifs        exfat     hostfs    nfs         proc        ubifs
coda        exportfs  hpfs      nfs_common  pstore      udf
文件系统简介
vfsVFS(Virtual Filesystem Switch)称为虚拟文件系统或虚拟文件系统转换,是一个内核软件层,在具体的文件系统之上抽象的一层,用来处理与Posix文件系统相关的所有调用,表现为能够给各种文件系统提供一个通用的接口,使上层的应用程序能够使用通用的接口访问不同文件系统,同时也为不同文件系统的通信提供了媒介
9p9P (Plan 9 File System Protocol),Plan 9 和 Inferno 使用的分布式文件系统协议
adfsADFS (Acorn Disc Filing System),Acron磁盘文件系统,RiscOS 操作系统中使用的标准文件系统
affsAmiga 计算机使用的文件系统
afsAFS (Andrew File System) 分布式文件系统
autofs自动挂载文件系统
befsBeOS 使用的文件系统
bfs数据库文件系统
btrfsBTRFS (B-tree, Butter FS, Better FS),是一款写时复制(CoW, Copy-on-Write)文件系统
cachefiles网络缓存文件系统
cephCeph是加州大学Santa Cruz分校的Sage Weil(DreamHost的联合创始人)专为博士论文设计的新一代自由软件分布式文件系统
cifs通用Internet文件系统(Common Internet File System,简写为CIFS),用于访问符合SNIA CIFS标准的服务器。CIFS对SMB协议进行改进和标准化(SMB协议可用于在Linux和Windows之间共享文件),是一种虚拟文件系统
codaCoda文件系统(Coda File System)适用于分布式网络环境。它是1987年在卡耐基梅隆大学以AFS2为原型开发出来的。Linux Virtual Server就采用了Coda文件系统
configfsconfigfs 是一个基于内存的文件系统,它提供了与sysfs相反的功能。sysfs 是一个基于文件系统的内核对象视图,而configfs 是一个基于文件系统的内核对象管理器(或称为config_items)
cramfsCRAMFS文件系统是专门针对闪存设计的只读压缩的文件系统
crypto加密文件系统
debugfs调试文件系统
devpts设备文件系统
dlm内核或用户空间的通用分布式锁管理器
ecryptfseCryptfs是Linux平台下的企业文件加密系统。它起源于Erez Zadok’s Cryptfs,通过FiST框架实现层叠式文件系统
efivarfs从 linux 3.8 开始,内核中添加的一个新的文件系统,efivarfs文件系统是为了解决在sysfs中使用entries来维EFIvariables的缺点
efsEFS是用于非ISO9660 CD-ROM的较旧文件系统
erofsEROFS(增强型只读文件系统)华为的EROFS超级文件系统,Linux内核5.4中也正式将华为EROFS超级文件系统合入了主线
exfatexFAT(Extended File Allocation Table File System,扩展FAT,即扩展文件分配表)是Microsoft在Windows Embeded 5.0 以上(包括Windows CE 5.0、6.0、Windows Mobile5、6、6.1)中引入的一种适合于闪存的文件系统,为了解决FAT32等不支持4G及其更大的文件而推出。对于闪存,NTFS文件系统不适合使用,exFAT更为适用。对于磁盘则不太适用
exportfs用于文件系统导出支持
ext2专门为Linux系统设计的文件系统,具有速度快和CPU占用率低等选特点。既可以用于标准的块设备,也可以应用到移动存储介质上。ext2不包括日志功能
ext4与ext2相比包含了日志功能,维护了最近更改的源数据(和文 件有关的信息,包括权限、所有者、创建时间、访问时间等)的记录,如果源数据由于非法关机等原因遭到破坏,文件系统将不能正常工作。通过ext4的日志系 统,可以对源数据进行适当的恢复。此外,ext3的日志功能可使硬盘读写头的移动达到最佳化
f2fsF2FS (Flash Friendly File System) 是专门为基于 NAND 的存储设备设计的新型开源 flash 文件系统。特别针对NAND 闪存存储介质做了友好设计。F2FS 于2012年12月进入Linux 3.8 内核。F2FS仅支持Linux操作系统
fatFAT是文件配置表(英语:File Allocation Table,首字母缩略字:FAT),是一种由微软发明并拥有部分专利的文件系统,供MS-DOS使用,也是所有非NT核心的微软窗口使用的文件系统
freevxfsFreeVxFS是支持VERITAS VxFS(TM)的文件系统
fscacheFacebook在Linux上实现硬盘级的Flashcache/Bcache来应对大数据存储的挑战
fuse用户空间文件系统
gfs2GFS2 是一个基于 GFS的先进的集群文件系统
hfsMAC下常用的混合文件系统
hfsplusHFS Plus 或者HFS+是苹果公司 (Apple)的MAC机所使用的光盘文件系统,为了取代混合文件系统 (Hybrid File System-HFS)。这同时也是数字音乐播放器iPOD用的格式
hostfs主机文件系统
hpfsHPFS一般指高性能文件系统。高性能文件系统 (High Performance File System ,HPFS),HPFS是Microsoft的LAN Manager中的文件系统,同时也是IBM的LAN Server和OS/2产品
hugetlbfs内存大页面支持特殊文件系统
iomap输入输出映射
isofs从High Sierra(CD-ROM使用的最初标准)发展而来的光盘文件系统,是CD-ROM的标准文件系统
jbd2jbd的全拼是journaling block driver 文件系统的日志功能,jbd2是ext4文件系统版本。自从Linux系统引入了Ext4文件系统了,就有一个JBD2为之服务,其实JBD2也可以为其它的文件系统服务,但是目前来说只有Ext4和OCFS2文件系统用它
jffs2JFFS2的全名为Journalling Flash File System Version2(闪存日志型文件系统第2版),其功能就是管理在MTD设备上实现的日志型
文件系统
jfsJFS( JOURNAL FILE SYSTEM),一种字节级日志文件系统,借鉴了数据库保护系统的技术,以日志的形式记录文件的变化
kernfs内核虚拟文件系统
lockdLinux锁管理器
minixMINIX操作系统中的原生文件系统,只支持长度为30字符以下的文件名
netfs
nfs网络文件系统,英文Network File System(NFS),是由SUN公司研制的UNIX表示层协议(presentation layer protocol),能使使用者访问网络上别处的文件就像在使用自己的计算机一样
nfs_commonNFS客户端和服务器共享的Linux文件系统例程
nfsdNFS服务器支持
nilfs2NILFS2 是一种 Log-Structure File System。最早的 Log-Structure File System 由 TCL/TK 语言的创始人 John Kenneth Ousterhout 在 Sprite 操作系统中实现。其基本思想是将底层设备当作一种只能追加写 (append) 的设备。将文件修改顺序追加写入磁盘,而不覆盖旧数据。顺序写入能避免很多寻道 (seek) 操作。seek 是一种机械操作,很难提高速度。因此减少 seek 能极大提高文件系统的写效率
nls文件系统本地语言支持
notify文件系统变化通知机制
ntfsNTFS文件系统最早出现于1993年的Windows NT操作系统中,它的出现大幅度地提高了微软原来的FAT文件系统的性能
ocfs2OCFS1问世于2002年10月,它是Oracle公司为了让RAC用户避免必须要与裸设备打交道而开发出来的。这个文件系统用来存放数据库相关的文件,比如数据文件,控制文件,在线日志文件,归档日志文件等。OCFS2是下一代的ORACLE集群文件系统,它已经被设计成为一种通用的文件系统,它不仅可以存放数据库相关的文件,还可以存放oracle二进制文件(指Oracle_home下的软件文件-译者注)和配置文件,从而使RAC的管理更加轻松
omfsOMFS是由SonicBlue公司创建的用于ReplayTV DVR和MP3 player的文件系统
openpromfsLinux Sun Openprom文件系统
orangefsOrangeFS 分布式文件系统
overlayfsOverlayfs是一种类似aufs的一种堆叠文件系统,于2014年正式合入Linux-3.18主线内核,目前其功能已经基本稳定(虽然还存在一些特性尚未实现)且被逐渐推广,特别在容器技术中更是势头难挡
proc基于内存的伪文件系统,不占用外存空间,只是以文件的方式为访问Linux内核数据提供接口。由于proc文件系统是虚拟的,所以无需挂载。用户和应用程序可以通过/proc得到系统的运行信息,并可以改变内核的某些参数
pstore主要用于存储内核异常时的log信息。实现方式是,管理一块“非易失性的存储空间”,如不断电的RAM或外部存储,当系统异常时,将log信息写到Pstore管理的存储空间,直到下一次系统正常时,在将log读出来,以文件形式提供给用户使用
qnx4黑莓(BlackBerry QNX)操作系统的实时文件系统
qnx6黑莓(BlackBerry QNX)操作系统的实时文件系统
quota设置磁盘限制使用情况(也称为磁盘配额)。目前,它适用于ext2,ext3,ext4,jfs,ocfs2和reiserfs文件系统
ramfsramfs是Linux下一种基于RAM做存储的文件系统
reiserfsReiserFS是一个非常优秀的文件系统。也是最早用于Linux的日志文件系统之一。ReiserFS的开发者非常有魄力,整个文件系统完全是从头设计的。目前,ReiserFS可轻松管理上百G的文件系统,这在企业级应用中非常重要
romfsROMFS是一种简单的只读文件系统,主要是用来当做初始文件系统来使用的,在嵌入式linux或是uclinux中通常使用这种文件系统来作为引导系统,甚至uclinux有时就直接把ROMFS作为其根文件系统,而不是将其作为系统启动中的过渡文件系统
squashfsSquashFS是一套基于Linux内核使用的压缩只读文件系统。该文件系统能够压缩系统内的文档,inode以及目录,文件最大支持2^64字节。SquashFS是基于GPL协议的开源软件。初始的版本使用gzip压缩,2.6.34版本Linux内核增加了支持LZMA和LZO压缩,并且在2.6.38内核版本上增加支持XZ压缩
sysfssysfs是一个基于内存的文件系统,它的作用是将内核信息以文件的方式提供给用户程序使用。sysfs可以看成与proc,devfs和devpty同类别的文件系统,该文件系统是虚拟的文件系统,可以更方便对系统设备进行管理。它可以产生一个包含所有系统硬件层次视图,与提供进程和状态信息的proc文件系统十分类似
sysvUNIX中最常用的system V文件系统
tracefstracefs是用于激活跟踪的伪文件系统
ubifs无序区块镜像文件系统(Unsorted Block Image File System, UBIFS)是用于固态存储设备上,并与LogFS相互竞争,作为JFFS2的后继文件系统之一。UBIFS由IBM与Nokia的工程师Thomas Gleixner,Artem Bityutskiy所设计,开发于2007年,并于2008年10月第一次加入Linux核心2.6.27版。专门为了解决MTD(Memory Technology Device)所遇到的瓶颈。由于Nand Flash容量的暴涨,YAFFS等皆无法操控大的Nand Flash空间。UBIFS通过子系统UBI处理与MTD device之间的动作。与JFFS2一样,UBIFS 建构于MTD之上,因而与一般的块设备不兼容。UBIFS在设计与性能上均较YAFFS2、JFFS2更适合MLC NAND FLASH。例如:UBIFS 支持 凑数(write-back), 其写入的数据会被缓存起来, 直到有必要写入时才写到flash, 这样大大降低分散小区块数量,并提高读写效率。UBIFS文件系统目录存储在flash上,UBIFS 挂载时不需要扫描整个存储器来重新创建文件目录。支持实时压缩,而且可选择性压缩部份文件。另外UBIFS使用日志(journal),可减少对flash index的更新频率。UBIFS 是 Nokia N900 智能手机上的默认文件系统
udfUDF 是统一光盘格式 (Universal Disc Format)的英文缩写 ,由国际标准化组织于1996 年制定的通用光盘文件系统 。它采用标准的包刻录技术 (PW ,Packet Writing)来简化刻录机的使用。UDF文件系统使用户可以如同操作硬盘那样来使用CD-RW刻录机
ufsUFS是UNIX文件系统的简称,它来源于4.3Tahoe发行版中提供的BSD Fat Fast File System(FFS)系统,属于FFS的演化版本。UFS几乎是大部分UNIX类操作系统默认的基于磁盘的文件系统,包括Solaris、Free BSD、Open BSD、Net BSD、HP-UX等,甚至Apple的OS X也能支持UFS文件系统
unicodeUnicode是一种宽字符集,用来支持UTF-8字符
vboxsfVirtualBox虚拟机来宾共享文件夹支持
verity基于文件的只读真实性效验
xfsXFS一种高性能的日志文件系统,最早于1993年,由Silicon Graphics为他们的IRIX操作系统而开发,是IRIX 5.3版的默认文件系统。2000年5月,Silicon Graphics以GNU通用公共许可证发布这套系统的源代码,之后被移植到Linux 内核上。XFS 特别擅长处理大文件,同时提供平滑的数据传输。XFS 最初是由 Silicon Graphics,Inc. 于 90 年代初开发的。那时,SGI 发现他们的现有文件系统(existing filesystem,EFS)正在迅速变得不适应当时激烈的计算竞争。为解决这个问题,SGI 决定设计一种全新的高性能 64 位文件系统,而不是试图调整 EFS在先天设计上的某些缺陷。因此,XFS 诞生了,并于 1994 年随 IRIX 5.3 的发布而应用于计算
zonefs西部数据开发的Zonefs已经确定要在Linux 5.6内核中登场了,这并不是一个传统意义上面的通用文件系统(比如Ext4、NTFS),而是一个针对特定硬件设备的文件系统,它为分区式存储设备进行了高度的优化。SMR HDD(叠瓦式硬盘)有一个毛病,它只有在顺序写入时才能正常发挥性能,一旦要进行数据覆盖写入,就需要改写这块数据所在区块内的所有磁道,造成严重的性能下降。传统的文件系统不会因为SMR HDD的特性而特别对待它,而Zonefs就是西部数据对SMR HDD和其他分区式存储设备提出的优化方案。它在传统的块设备之外提供了另一种映射,将分区式存储设备上面的每一个区都映射成一个单独的文件,这带来的好处就是应用程序无需修改太多的代码即可利用上分区式存储设备的优点,很多原本要自己做的控制都被集成在Zonefs里面了,不用开发者来动手了,这大大减少了使用分区式存储设备的迁移工作量

文件 /proc/filesystems 记录了 Linux 内核支持的文件系统列表(包括已编译到内核或当前加载其内核模块的文件系统):

canpool@DESKTOP-ODCM7SC:~$ cat /proc/filesystems
nodev   sysfs
nodev   rootfs
nodev   bdev
nodev   proc
nodev   tmpfs
nodev   binfmt_misc
nodev   debugfs
nodev   sockfs
nodev   usbfs
nodev   pipefs
nodev   anon_inodefs
nodev   devpts
ext3
ext2
ext4
nodev   ramfs
nodev   hugetlbfs
vfat
msdos
iso9660
fuseblk
nodev   fuse
nodev   fusectl
yaffs
yaffs2
nodev   overlayfs
nodev   overlay
nodev   mqueue

如果文件系统标有“nodev”,则不需要挂载块设备。例如:虚拟文件系统、网络文件系统等都是“nodev”的例子。

3.2. 文件系统特性

3.2.1. 格式化

我们都知道磁盘分区完毕后还需要进行格式化(format),之后操作系统才能够使用这个文件系统。

格式化,顾名思义,就是按一定格式进行初始化。因为每种操作系统所设定的文件属性/权限并不相同,为了存放这些文件所需的数据,因此就需要将分区槽进行格式化,以成为操作系统能够利用的文件系统格式。

由此我么也能够知道,每种操作系统能够使用的文件系统并不相同。举例来说,windows 98 以前的微软操作系统主要利用的文件系统是 FAT(或FAT16),windows 2000 以后的版本使用 NTFS 文件系统。至于 Linux 的正统文件系统则为 Ext2(Linux second extended file,ext2fs)。

传统的磁盘与文件系统之应用中,一个分区槽就是只能够被格式化成为一个文件系统,所以我们可以说一个 filesystem 就是一个 partition。但是由于新技术的利用,例如我们常听到的 LVM(Logical Volume Manager,逻辑卷管理)与软件磁盘阵列(software raid),这些技术可以将一个分区槽格式化为多个文件系统(LVM),也能够将多个分区槽合成一个文件系统(LVM,RAID)。所以说,目前我们在格式化时已经不再说成针对 partition 来格式化了,通常我们可以称呼一个可被挂载的数据为一个文件系统而不是一个分区槽。

3.2.2. 格式

我们知道文件除了文件实际内容外,通常还还有非常多的属性,例如 Linux 操作系统的文件权限(rwx)与文件属性(拥有者、群组、时间参数等)。文件系统通常会将这两部分的数据分别存放在不同的区块中,权限与属性放到 inode 节点中,至于实际数据则放到 block 区块中。另外,还有一个超级区块(superblock)会记录整个文件系统的整体信息,包括 inode 与 block 的总量、使用量、剩余量等。

每个 indoe 与 block 都有编号,至于这三个数据的意义可以简略说明如下:

  • superblock:记录此 filesystem 的整体信息,包括 inode/block 的总量、使用量、剩余量,以及文件系统的格式与相关信息等;
  • inode:记录文件的属性,一个文件占用一个 inode,同时记录此文件的数据所在的 block 编号;
  • block:记录文件的实际内容,若文件太大时,会占用多个 block。

由于每个 inode 与 block 都有编号,而每个文件都会占用一个 inode,inode 内则有文件数据放置的 block 编号。因此,我们可以知道的是,如果能够找到文件的 inode 的话,那么自然就会知道这个文件所放置数据的 block 编号,当然也就能够读出该文件的实际数据了。这是个比较有效率的做法,因为如此一来我们的磁盘就能够在短时间内读取出全部的数据,读写的效能都比较好。

我们将 indoe 与 block 用图解来说明一下,如果下图所示,文件系统先格式化出 inode 与 block,假设某一个文件的属性和权限数据是放置到 inode 4 号,而这个 indoe 记录了文件数据的实际放置点为 2、7、13、15 这四个 block 号码,此时我们的操作系统就能够据此来排列磁盘的阅读顺序,可以一口气将四个 block 内容读出来。那么数据的读取就如同下图中的箭头所指定的模样:

这种数据存取的方法我们称为索引文件系统(indexed allocation)。下图是 FAT 文件系统的数据读取方式,FAT 格式并没有 indoe,所以没办法将文件的所有 block 在一开始就读取出来。每个 block 编号都记录在前一个 block 当中,如下所示:

上图中我们假设文件的数据依序写入 1->7->4->15 这四个 block 中,但这个文件系统没办法一口气就知道四个 block 的编号,得一个一个的将 block 读出后,才会知道下一个 block 在何处。如果同一个文件数据写入的 block 分散的太过厉害时,则我们的磁盘读取头将无法在磁盘转一圈就读到所有的数据,因此磁盘就会多转好几圈才能完整的读取到这个文件的内容。

3.3. EXT 族文件系统

3.3.1. EXT2 文件系统

标准的 Linux 文件系统 Ext2 就是使用 inode 为基础的文件系统。

一般文件系统一开始就将 inode 与 block 规划好了,除非重新格式化(或者利用 resize2fs 等指令变更文件系统大小),否则 inode 与 block 固定后就不再变动。但是仔细考虑一下,如果我们的文件系统高达数百 GB 时,那么将所有的 indoe 与 block 通通放置在一起将是很不明智的决定,因为 inode 与 block 的数量太庞大,不容易管理。

因此 Ext2 文件系统在格式化的时候基本上是区分为多个区块群组(block group)的,每个区块群组都有独立的 inode/block/superblock 系统。Ext2 格式化后如下所示:

在整体的规划当中,文件系统最前面有一个启动扇区(boot sector),这个启动扇区可以安装开机管理程序,这是个非常重要的设计,因为如此一来我们就能够将不同的开机管理程序安装到个别的文件系统最前端,而不用覆盖整个磁盘唯一的 MBR(Master Boot Record,主引导记录,是采用MBR分区表的硬盘的第一个扇区),这样也才能够制作出多重引导的环境。

3.3.1.1. data block(数据区块)

data block 是用来放置文件内容数据的地方,在 Ext2 文件系统中所支持的 block 大小有 1K,2K,4K 三种。在格式化时 block 的大小就固定了,且每个 block 都有编号,以方便 inode 记录。不过要注意的是,由于 block 大小的差异,会导致该文件系统能够支持的最大磁盘容量与最大单一文件容量并不相同。因为 block 大小而产生的 Ext2 文件系统限制如下:

Block大小1KB2KB4KB
最大单一文件限制16GB256GB2TB
最大文件系统总容量2TB8TB16TB

除此之外,Ext2 文件系统的 block 还有一些基本限制如下:

  • 原则上,block 的大小和数量在格式化完就不能够再改变(除非重新格式化);
  • 每个 block 内最多只能够放置一个文件的数据;
  • 如果文件大于 block 的大小,则一个文件会占用多个 block 数量;
  • 若文件小于 block,则该 block 的剩余容量就不能够再被使用(磁盘空间会浪费)。

由于每个 block 仅能容纳一个文件的数据而已,因此如果你的文件都非常小,但是你的 block 在格式化时却选用最大的 4K 时,可能会产生一些容量的浪费。但也不能就此将 block 选为 1K,因为如果 block 较小的话,那么大型文件将会占用数量更多的 block,而 inode 也要记录更多的 block 编号,此时将可能导致文件系统不良的读写效能。事实上,现在的磁盘容量都太大了,基本都选择 4K 的 block 大小。

3.3.1.2. inode table(节点表)

inode 记录的文件数据至少包含如下内容:

  • 该文件的存取模式(read/write/excute)
  • 该文件的拥有者与群组(owner/group)
  • 该文件的容量
  • 该文件建立或状态改变的时间(ctime)
  • 该文件最近一次读取时间(atime)
  • 该文件最近修改的时间(mtime)
  • 该文件的特性标记(flag),如:setuid
  • 该文件真正内容的指向(pointer)

inode 的数量与大小也是在格式化时就已经固定了,除此之外 inode 还有一些特点:

  • 每个 inode 大小均固定为 128B(新的 ext4 与 xfs 可设定到 256B)
  • 每个文件都仅会占用一个 inode
  • 因此文件系统能够建立的文件数量与 inode 的数量有关
  • 系统读取文件时,需要先找到 inode,并分析 inode 所记录的权限与用户是否符合,若符合才能够开始实际读取 block 的内容。

下面分析一下 Ext2 的 inode/block 与文件大小的关系。inode 要记录的数据非常多,但其大小仅有 128B,而 inode 记录一个 block 编号需要 4B。假设一个文件有 400MB 且每个 block 为 4K 时,那么至少也要有十万笔 block 编号的记录,而一个 inode 根本记录不了这么多 block 编码。为此,Ext2 将 inode 记录 block 编号的区域定义为 12个直接,1个间接,1个双间接与1个三间接记录区。下图是 inode 的大概结构图:

上图最左边为 inode 本身(128B),里面有 12 个直接指向 block 编号,这 12 个记录就能够直接取得 block 编号。至于所谓的间接就是再拿一个 block 来当做记录 block 编号的记录区,如果文件太大时,就会使用间接的 block 来记录编号。如上图中间接只是拿一个 block 来记录额外的编号而已。同理,如果文件持续长大,那么就会利用所谓的双间接,第一个 block 仅再指出下一个记录编号的 block 在哪里,实际记录的在第二个 block 当中。以此类推,三间接就是利用第三层 block 来记录编号,即所谓级联。

我们以 1K 大小的 block 来计算一下 inode 最多能够记录多少个 block:

  • 12直接:12 * 1K = 12K

    由于是直接指向,所以总共可记录 12 个 block 编号。

  • 一间接:256 * 1K = 256K

    每笔 block 编号的记录需要 4B,因此 1K 大小的 block 能够记录 256 个 block 编号。

  • 双间接:256 * 256 * 1K = 256^2K

    第一层 block 会指定 256 个第二层,每个第二层可以记录 256 个 block 编号。

  • 三间接:256 * 256 * 256 * 1K = 256^3K

    第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个第三层,每个第三层可以指定 256 个 block 编号。

  • 总额:将直接、间接、双间接、三间接加总,得到 12K + 256K + 256256K + 256256*256K = 16G

此时,我们知道当文件系统将 block 格式化为 1K 大小时,能够容纳的最大文件为 16G,比较一下上节文件系统限制表的结果可发现是一致的。但这个方法不能用在 2K,4K 大小的计算中,因为大于 2K 的 block 将会受到 Ext2 文件系统本身的限制,所以计算的结果会不太符合。

3.3.1.3. inode bitmap(节点位图)

inode bitmap 记录使用与未使用的 inode 编号。

3.3.1.4. block bitmap(区块位图)

新增文件时,需要用到空的 block,从 block bitmap 中可以知道哪些 block 是空的,因此系统能够很快速的找到可使用的空间来处理文件。

同样的,如果你删除某个文件时,那么那些文件原本占用的 block 编号就得要释放出来,此时在 block bitmap 当中相对应到该 block 编号的标志就得要修改称为“未使用中”。

3.3.1.5. filesystem description(文件系统描述说明)

这个区段可以描述每个 block group 的开始与结束的 block 编号,以及说明每个区段(superblock,bitmap,inodemap,data block)分别介于哪一个 block 编号之间。

3.3.1.6. superblock(超级区块)

superblock 是记录整个 filesystem 相关信息的地方,记录的信息主要有:

  • block 与 inode 的总量;
  • 未使用与已使用的 inode/block 数量;
  • block 与 inode 的大小(block 为 1,2,4K,inode 为 128B 或 256B);
  • filesystem 的挂载时间、最近一次写入数据的时间、最近一次检测磁盘(fsck)的时间等文件系统的相关信息;
  • 一个 valid bit 数值,若此文件系统已被挂载,则 valid bit 为 0,若未被挂载,则 valid bit 为 1。

superblock 因记录了文件系统的基本信息,所以非常重要。每个 block group 都可能含有 superblock,但是我们也说一个文件系统应该仅有一个 superblock。事实上,除了第一个 block group 内会含有 superblock 之外,后续的 block group 不一定含有 superblock,若含有 superblock 则该 superblock 主要是作为第一个 block group 内 superblock 的备份,这样当 第一个 superblock 出问题时,其它 superblock 就可以用来救援。

3.3.2. 与目录树的关系

Linux 系统下,每个文件(不管是一般文件,还是目录文件)都会占用一个 inode,且可依据文件内容的大小来分配多个 block 给该文件使用。目录的内容在记录文件名,一般文件才是实际记录数据内容的地方。接下来,介绍目录与文件在文件系统当中是如何记录数据的。

3.3.2.1. 目录

当我们在 Linux 下的 ext2 文件系统中建立一个目录时,文件系统会分配一个 inode 与至少一块 block 给该目录。其中,inode 记录该目录的相关权限与属性,并记录分配到的 block 编号;而 block 则是记录在这个目录下的文件名与该文件名占用的 inode 编号数据。也就是说目录所占用的 block 内容在记录如下的信息:

inode number文件名
2814749767128867alias.sh
3096224743839528array.sh

可以通过ls -li查看目录内的文件所占用的 inode 编号,如下所示:

canpool@DESKTOP-ODCM7SC:~/projects/canpool/shcanpool/src/utils$ ls -li
total 8
2814749767128867 -rwxrwxrwx 1 canpool canpool 716 Jun  6 23:53 alias.sh
3096224743839528 -rwxrwxrwx 1 canpool canpool 787 Jun  6 23:53 array.sh
2251799813711171 -rwxrwxrwx 1 canpool canpool 167 Jun  6 23:53 declare.sh
2814749767128871 -rwxrwxrwx 1 canpool canpool 788 Jun  6 23:53 dict.sh
2814749767128874 -rwxrwxrwx 1 canpool canpool 458 Jun  6 23:53 method.sh
2814749767128905 -rwxrwxrwx 1 canpool canpool 356 Jun  6 23:53 string.sh
3377699720553796 -rwxrwxrwx 1 canpool canpool 488 Jun  6 23:53 type.sh

由目录记录数据的特点而知,当使用ll时,出现的目录几乎都是 block 大小的倍数。

3.3.2.2. 文件

当我们在 Linux 下的 ext2 文件系统中建立一个一般时,文件系统会分配一个 inode 与相对于该文件大小的 block 数量给该文件。

例如:假设我的一个 block 为 4K,而我要建立一个 100K 的文件,那么 linux 将分配一个 inode 与 25 个 block 来储存该文件。但同时请注意,由于 inode 仅有 12 个直接指向,因此还要多一个 block 来作为区块号码的记录。

3.3.2.3. 目录树读取

目录的 inode 本省并不记录文件名,文件名的记录是在目录的 block 当中。因此新增/删除/更名文件与目录的写(w)权限有关。因为文件名是记录在目录的 block 当中,因此当要读取某个文件时,就务必会经过目录的 inode 与 block,然后才能够找到那个待读取文件的 inode 编号,最终才会读到正确的文件的 block 内的数据。

由于目录树是由根目录开始读起,因此系统透过挂载的信息可以找到挂载点的 inode 号码,此时就能够得到根目录的 inode 内容,并依据该 inode 读取根目录的 block 内的文件名数据,再一层一层的往下读到正确的文件名。

以读取 /etc/passwd 这个文件为例,讲解系统是如何读取的:

[maminjie@fedora ~]$ ll -di / /etc /etc/passwd
   256 dr-xr-xr-x. 1 root root  158 May  5 05:27 /
   270 drwxr-xr-x. 1 root root 4606 Jun  6 21:17 /etc
153255 -rw-r--r--. 1 root root 2475 May 31 20:47 /etc/passwd
  1. / 的 inode

    透过挂载点的信息找到 inode 号码为 256 的根目录 inode,且 inode 规范的权限让我们可以读取该 block 的内容(有r与x)。

  2. / 的 block

    经过上个步骤取得 block 号码,并找到该内容中 etc/ 目录的 inode 号码(270)。

  3. etc/ 的 inode

    读取 270 号 inode 得知具有 r 与 x 的权限,因此可以读取 etc/ 的 block 内容。

  4. etc/ 的 block

    经过上个步骤取得 block 号码,并找到该内容中 passwd 文件的 inode 号码(153255)。

  5. passwd 的 inode

    读取 153255 号 inode 得知具有 r 的权限,因此可以读取 passwd 的 block 内容。

  6. passwd 的 block

    最后将该 block 内容的数据读出来。

以上只是简单模拟层层读取内容背后的逻辑。

3.3.3. EXT3/4 文件系统

3.3.3.1. 文件的存取

上面仅谈到读取,当新建一个文件时,文件系统的行为是:

  1. 先确定用户对于将要新增文件的目录是否具有 w 与 x 的权限,若有的话才能新增;
  2. 根据 inode bitmap 找到没有使用的 inode 号码,并将新文件的权限/属性写入;
  3. 根据 block bitmap 找到没有使用的 block 号码,并将实际的数据写入 block 中,且更新 inode 的 block 指向的数据;
  4. 将刚刚写入的 inode 与 block 数据同步更新 inode bitmap 与 block bitmap,并更新 superblock 的内容。

一般来说,我们将 inode table 与 data block 称为数据存放区域,其它例如 superblock、block bitmap、inode bitmap 等区段就被称为 metadata(中介数据)。因为 superblock、inode bitmap 及 block bitmap 的数据是经常变动的,每次新增、移除、编辑时都可能会影响到这三个部分的数据,因此才被称为中介数据。

3.3.3.2. 数据不一致状态

在一般正常的情况下,上述的新增动作当然可以顺利的完成。但是,如果文件在写入文件系统时,因为不知名原因导致系统中断(例如突然断电,系统发生错误等),所写入的数据仅有 inode table 即 data block,最后一个同步更新中介数据的步骤没有完成,此时就会发生 metadata 的内容与实际数据存放区产生不一致的情况。

早期的 ext2 文件系统中,如果发生这个问题,那么系统在重新启动的时候,就会由 superblock 当中记录的 valid bit(是否有挂载)与 filesystem stat(clean与否)等状态来判断是否强制进行数据一致性的检查(检查程序为e2fsck)。

不过,这样的检查很费时,所以后来就出现了日志式文件系统。

3.3.3.3. 日志式文件系统

为了避免上述提到的文件系统不一致的情况发生,设计者在文件系统中规划出一个区块,该区块专门记录写入或修订文件,如下:

  1. 预备:当系统要写入一个文件时,会先在日志记录区块中记录某个文件准备要写入的信息
  2. 实际写入:开始写入文件的权限与数据;开始更新 metadata 的数据;
  3. 结束:完成数据与 metadata 的更新后,在日志记录区块当中完成该文件的记录。

在这样的程序当中,万一数据在记录过程当中发生了问题,那么我们的系统只要去检查日志记录区块,就可以知道哪个文件发生了问题,针对该问题做一致性的检查即可。

目前 ext2 不具备该功能,但是 ext3/ext4 已具备,ext3/ext4 是 ext2 的升级版本,并且可向下兼容 ext2 版本。

3.4. 挂载点的意义

每个文件系统都有独立的 inode/block/superblock 等信息,这个文件系统要能够链接到目录树才能被我们使用。将文件系统与目录树结合的动作我们称为挂载。

挂载点一定是目录,该目录为进入该文件系统的入口。因此并不是你有任何文件系统都能使用,必须要挂载到目录树的某个目录后,才能够使用该文件系统。

[maminjie@fedora ~]$ df -hT
Filesystem     Type              Size  Used Avail Use% Mounted on
devtmpfs       devtmpfs          4.0M     0  4.0M   0% /dev
tmpfs          tmpfs             969M     0  969M   0% /dev/shm
tmpfs          tmpfs             388M  1.7M  386M   1% /run
/dev/sda2      btrfs              19G  5.0G   14G  27% /
/dev/sda2      btrfs              19G  5.0G   14G  27% /home
/dev/sda1      ext4              974M  172M  735M  19% /boot
tmpfs          tmpfs             969M  212K  968M   1% /tmp
tmpfs          tmpfs             194M  144K  194M   1% /run/user/1000
/dev/sr0       iso9660           1.9G  1.9G     0 100% /run/media/maminjie/Fedora-WS-Live-36-1-5
vmhgfs-fuse    fuse.vmhgfs-fuse  304G  110G  194G  37% /mnt/hgfs
[maminjie@fedora ~]$ ls -lid / /home /boot
256 dr-xr-xr-x. 1 root root  158 May  5 05:27 /
  2 dr-xr-xr-x. 7 root root 4096 Jun  1 04:25 /boot
256 drwxr-xr-x. 1 root root   16 May 31 20:47 /home

通过上面发现 / 和 /home 的 inode 都为 256,因为这两个目录挂载的文件系统相同,且作为文件系统的顶层目录。对于相同文件系统的顶层目录,其 inode 是相同的。

我们知道根目录下的 . 与 … 是相同的东西,因为它们都等效于 /。如果从文件系统的观点来看,同一个文件系统的一个文件占用一个 inode,如果几个文件的 inode 相同,那说明这几个文件内容是一样的,通过查看这三个文件的信息,其 inode 确实也都是一样的,如下所示:

[maminjie@fedora ~]$ ls -lid / /. /..
256 dr-xr-xr-x. 1 root root 158 May  5 05:27 /
256 dr-xr-xr-x. 1 root root 158 May  5 05:27 /.
256 dr-xr-xr-x. 1 root root 158 May  5 05:27 /..

3.5. 虚拟文件系统

Linux 上的文件系统实际上是由 VFS(Virtual Filesystem Switch,虚拟文件系统)管理的。假设 /dev/sda1 挂载到 / 并使用 ext3 文件系统,/dev/sda2 挂载到 /home 并使用 reiserfs,那么当你读取 /home/canpool/.bashrc 时,并没有特别指定要用的什么文件系统的模块来读取,这就是 VFS 在背后起到的作用。这个 VFS 可以简单用下图说明:

3.6. 文件系统简单操作

3.6.1. 磁盘与目录的容量

现在我们知道磁盘的整体数据在 superblock 区块中,但是每个文件的容量则在 inode 当中记载。介绍如下两个命令:

  • df:列出文件系统的整体磁盘使用量;
  • du:评估文件系统的磁盘使用量(常用在估算目录所占容量)。
3.6.1.1. df
简单用法:
df [-ahikHTm] [目录或文件名]

选项与参数:
-a      列出所有的文件系统,包括系统特有的 /proc 等文件系统;
-k      以 KByte 的容量显示各文件系统
—m      以 MByte 的容量显示各文件系统
-h      以人们易读的 GByte,MByte,KByte 等格式自行显示
-H      以 M=1000K 取代 M=1024K 的进位方式
-T      连同该 partition 的 filesystem 名称也列出
-i      不用磁盘容量,而以 inode 的数量来显示

范例一:将系统内所有的 filesystem 列出来

maminjie@fedora ~]$ df
Filesystem     1K-blocks      Used Available Use% Mounted on
devtmpfs            4096         0      4096   0% /dev
tmpfs             991364         0    991364   0% /dev/shm
tmpfs             396548      1672    394876   1% /run
/dev/sda2       19921920   5171988  14567052  27% /
/dev/sda2       19921920   5171988  14567052  27% /home
/dev/sda1         996780    175844    752124  19% /boot
tmpfs             991368       212    991156   1% /tmp
tmpfs             198272       148    198124   1% /run/user/1000
/dev/sr0         1970848   1970848         0 100% /run/media/maminjie/Fedora-WS-Live-36-1-5
vmhgfs-fuse    317760508 114861452 202899056  37% /mnt/hgfs

如果 df 没有加任何选项,那么默认会将系统内所有的(不含特殊内存的文件系统与 swap)都以 1 KByte 的容量来列出来。

输出的各列说明如下:

  • Filesystem:代表该文件系统是在哪个 partition,所以列出设备名称
  • 1k-blocks:说明底下的数字单位是 1KB,可利用 -h 或 -m 来改变容量
  • Used:已用的空间大小
  • Available:剩下的空间大小
  • Use%:使用率
  • Mounted on:挂载点

范例二:将容量结果以易读的容量格式显示

[maminjie@fedora ~]$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        4.0M     0  4.0M   0% /dev
tmpfs           969M     0  969M   0% /dev/shm
tmpfs           388M  1.7M  386M   1% /run
/dev/sda2        19G  5.0G   14G  27% /
/dev/sda2        19G  5.0G   14G  27% /home
/dev/sda1       974M  172M  735M  19% /boot
tmpfs           969M  212K  968M   1% /tmp
tmpfs           194M  148K  194M   1% /run/user/1000
/dev/sr0        1.9G  1.9G     0 100% /run/media/maminjie/Fedora-WS-Live-36-1-5
vmhgfs-fuse     304G  110G  194G  37% /mnt/hgfs

范例三:将系统内的所有特殊文件格式及名称都列出来

[maminjie@fedora ~]$ df -aT
df: /run/user/1000/doc: Operation not permitted
Filesystem     Type             1K-blocks      Used Available Use% Mounted on
proc           proc                     0         0         0    - /proc
sysfs          sysfs                    0         0         0    - /sys
devtmpfs       devtmpfs              4096         0      4096   0% /dev
securityfs     securityfs               0         0         0    - /sys/kernel/security
tmpfs          tmpfs               991364         0    991364   0% /dev/shm
devpts         devpts                   0         0         0    - /dev/pts
tmpfs          tmpfs               396548      1672    394876   1% /run
cgroup2        cgroup2                  0         0         0    - /sys/fs/cgroup
pstore         pstore                   0         0         0    - /sys/fs/pstore
bpf            bpf                      0         0         0    - /sys/fs/bpf
/dev/sda2      btrfs             19921920   5171988  14567052  27% /
selinuxfs      selinuxfs                0         0         0    - /sys/fs/selinux
systemd-1      -                        -         -         -    - /proc/sys/fs/binfmt_misc
hugetlbfs      hugetlbfs                0         0         0    - /dev/hugepages
mqueue         mqueue                   0         0         0    - /dev/mqueue
debugfs        debugfs                  0         0         0    - /sys/kernel/debug
tracefs        tracefs                  0         0         0    - /sys/kernel/tracing
fusectl        fusectl                  0         0         0    - /sys/fs/fuse/connections
configfs       configfs                 0         0         0    - /sys/kernel/config
/dev/sda2      btrfs             19921920   5171988  14567052  27% /home
/dev/sda1      ext4                996780    175844    752124  19% /boot
tmpfs          tmpfs               991368       212    991156   1% /tmp
sunrpc         rpc_pipefs               0         0         0    - /var/lib/nfs/rpc_pipefs
tmpfs          tmpfs               198272       148    198124   1% /run/user/1000
gvfsd-fuse     fuse.gvfsd-fuse          0         0         0    - /run/user/1000/gvfs
/dev/sr0       iso9660            1970848   1970848         0 100% /run/media/maminjie/Fedora-WS-Live-36-1-5
vmhgfs-fuse    fuse.vmhgfs-fuse 317760508 114861452 202899056  37% /mnt/hgfs
binfmt_misc    binfmt_misc              0         0         0    - /proc/sys/fs/binfmt_misc

系统里面其实还有很多特殊的文件系统存在。那些比较特殊的文件系统几乎都是在内存中,例如 /proc 这个挂载点。因此,这些特殊的文件系统都不会占据磁盘空间。

范例四:将 /etc 目录的可用磁盘容量以易读的格式显示

[maminjie@fedora ~]$ df -h /etc
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2        19G  5.0G   14G  27% /

在 df 后面加上目录或文件时,df 会自动的分析该目录或文件所在的 partition,并将该 partition 的容量显示出来。

范例五:将目前各个 partition 当中可用的 inode 数量列出

[maminjie@fedora ~]$ df -ih
Filesystem     Inodes IUsed IFree IUse% Mounted on
devtmpfs         1.0M   494  1.0M    1% /dev
tmpfs            243K     1  243K    1% /dev/shm
tmpfs            800K   978  800K    1% /run
/dev/sda2           0     0     0     - /
/dev/sda2           0     0     0     - /home
/dev/sda1         64K   449   64K    1% /boot
tmpfs            1.0M    50  1.0M    1% /tmp
tmpfs             49K   145   49K    1% /run/user/1000
/dev/sr0            0     0     0     - /run/media/maminjie/Fedora-WS-Live-36-1-5
vmhgfs-fuse         0     0     0     - /mnt/hgfs

说明:作者的环境是VMware虚拟机,所有比较奇怪,有些 Inodes 列居然是 0。

3.6.1.2. du
简单用法:
du [-ahsSkm] 文件或目录名称

选项与参数:
-a      列出所有的文件与目录容量,因为默认仅统计目录下的文件容量而已
-h      以人们易读的 GByte,MByte,KByte 等格式自行显示
-s      列出总量,而不列出每个目录占用的容量
-S      不包括子目录下的总计,与 -s 有点差别
-k      以 KByte 的列出容量
—m      以 MByte 的列出容量

范例一:列出当前目录下的所有文件容量

[maminjie@fedora ~]$ du
...(省略)...
20	./.cache/gnome-software/fedora-pkgdb-collections
8272	./.cache/gnome-software/appstream
1268	./.cache/gnome-software/odrs
4	./.cache/gnome-software/langpacks
488	./.cache/gnome-software/flatpak-system-default
...(省略)...
4	./bin
0	./work
25848	.

du 不加任何选项是,则分析当前目录下的文件与目录所占用的磁盘空间。但是,实际显示时,仅会显示目录容量(不含文件)。因此,目录有很多文件没有被列出来,所以全部的目录相加不会等于 . 的容量。
此外,输出的数值数据位 1K 大小的容量单位。可以通过du -a将文件的容量也列出来。

范例二:检查当前目录下每个目录所占用的容量

[maminjie@fedora ~]$ du -sm ./*
1	./bin
0	./Desktop
0	./Documents
0	./Downloads
0	./Music
0	./Pictures
1	./projects
0	./Public
0	./Templates
0	./Videos
0	./work

与 df 不一样的是,du 其实会直接到文件系统内去搜寻所有的文件数据。

3.6.2. 实体链接与符号链接

Linux 下有两种文件链接方式:

  • 符号链接:类似 Windows 的快捷方式功能的文件,可以快速链接到目标文件(或目录),也称为“软链接”。
  • 实体链接:透过文件系统的 inode 链接来产生新文档名,而不是产生新文件,也称为“硬链接”。
3.6.2.1. ln
简单用法:
ln [-sf] 源文件 目标文件

选项与参数:
-s      如果不见任何参数就进行实体链接,至于 -s 就是符号链接
-f      如果目标文件存在,就主动的将目标文件直接移除再建立
3.6.2.2. 实体链接(hard link)

inode 的几个重要信息如下:

  • 每个文件都会占用一个 inode,文件内容由 inode 的记录来指向;
  • 想要读取该文件,必须要经过目录记录的文件名来指向正确的 inode 编号才能读取。

也就是说,其实文件名只与目录有关,但是文件内容则与 inode 有关。实体链接只是在某个目录下新增一个文文档名连接到某 inode 编号的关联记录而已。

举个例子来说,假设 a2 是 a1 的实体链接,也就是说这两个文件名链接到同一个 inode,自然这两个文件名的所有相关信息都一样(除了文件名)。实际情况如下:

[maminjie@fedora work]$ echo "1234" > a1
[maminjie@fedora work]$ ll -i a1
825 -rw-rw-r--. 1 maminjie maminjie 5 Jun 12 13:24 a1
[maminjie@fedora work]$ ln a1 a2
[maminjie@fedora work]$ ll -i a1 a2
825 -rw-rw-r--. 2 maminjie maminjie 5 Jun 12 13:24 a1
825 -rw-rw-r--. 2 maminjie maminjie 5 Jun 12 13:24 a2

可以发现这两个文件都链接到 825 这个 inode 号码,所以文件的权限/属性完全一样,而且第二个字段由原来的 1 变成了 2,这个字段称为链接数。读取数据的示意图如下:

上图的意思是,可以通过 1 或 2 的目录之 inode 指定的 block 找到两个不同的文件名,不管使用哪个文件名局可以找到 read 那个 inode 去读取到最终的数据。

一般来说,使用实体链接设定链接文件时,inode 的数目是不会改变的,只是在某个目录下的 block 多写一个关联数据而已。当新增的这笔数据刚好将目录的 block 填满时,就可能会新加一个 block 来记录文件名关联性。

实体链接的限制:不能跨文件系统,不支持链接目录。

3.6.2.3. 符号链接(symbolic link)

符号链接就是建立一个独立的文件,这个文件会让数据的读取执向它链接的那个文件名。

由于只是利用文件来作为指向的动作,所以,当源文件被删除之后,符号链接将打不开,找不到原始文件。

举例,假设 a3 是 a1 的符号链接:

[maminjie@fedora work]$ ln -s a1 a3
[maminjie@fedora work]$ ll -i a1 a3
825 -rw-rw-r--. 2 maminjie maminjie 5 Jun 12 13:24 a1
833 lrwxrwxrwx. 1 maminjie maminjie 2 Jun 12 14:15 a3 -> a1

可以发现两个文件指向不同的 inode 号码,它们是两个独立的文件,而且符号链接文件的重要内容就是它会协商目标文件的文件名。可以发现,链接文件的大小为 2B,因为文件 a1 的名字总共 2 个字符,每个字符占一个字节。操作示意图如下:

通过 3 号 inode 读取到链接的内容仅有文件名,根据文件名链接到正确的目录去取得目标文件的 inode,最终就能够读取到正确的数据。

符号链接建立的文件是一个独立的新文件,所以会占用新的 inode 和 block。

3.6.3. 文件系统信息

3.6.3.1. 查看文件系统类型

下面介绍几种查看 Linux 系统当前使用的文件系统类型。

1)mount 命令

[maminjie@fedora ~]$ mount
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel)
devtmpfs on /dev type devtmpfs (rw,nosuid,seclabel,size=4096k,nr_inodes=1048576,mode=755,inode64)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,seclabel,inode64)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,seclabel,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,seclabel,size=396548k,nr_inodes=819200,mode=755,inode64)
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,seclabel,nsdelegate,memory_recursiveprot)
pstore on /sys/fs/pstore type pstore (rw,nosuid,nodev,noexec,relatime,seclabel)
bpf on /sys/fs/bpf type bpf (rw,nosuid,nodev,noexec,relatime,mode=700)
/dev/sda2 on / type btrfs (rw,relatime,seclabel,compress=zstd:1,space_cache=v2,subvolid=257,subvol=/root)
selinuxfs on /sys/fs/selinux type selinuxfs (rw,nosuid,noexec,relatime)
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=43,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=1623)
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,seclabel,pagesize=2M)
mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime,seclabel)
debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec,relatime,seclabel)
tracefs on /sys/kernel/tracing type tracefs (rw,nosuid,nodev,noexec,relatime,seclabel)
fusectl on /sys/fs/fuse/connections type fusectl (rw,nosuid,nodev,noexec,relatime)
configfs on /sys/kernel/config type configfs (rw,nosuid,nodev,noexec,relatime)
/dev/sda2 on /home type btrfs (rw,relatime,seclabel,compress=zstd:1,space_cache=v2,subvolid=256,subvol=/home)
/dev/sda1 on /boot type ext4 (rw,relatime,seclabel)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,seclabel,size=991368k,nr_inodes=1048576,inode64)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw,relatime)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,seclabel,size=198272k,nr_inodes=49568,mode=700,uid=1000,gid=1000,inode64)
gvfsd-fuse on /run/user/1000/gvfs type fuse.gvfsd-fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
/dev/sr0 on /run/media/maminjie/Fedora-WS-Live-36-1-5 type iso9660 (ro,nosuid,nodev,relatime,nojoliet,check=s,map=n,blocksize=2048,uid=1000,gid=1000,dmode=500,fmode=400,iocharset=utf8,uhelper=udisks2)
portal on /run/user/1000/doc type fuse.portal (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
vmhgfs-fuse on /mnt/hgfs type fuse.vmhgfs-fuse (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,nosuid,nodev,noexec,relatime)

不加任何参数的 mount 命令,可以列出当前所有文件系统的挂载情况。

2)df 命令

[maminjie@fedora ~]$ df -Th
Filesystem     Type              Size  Used Avail Use% Mounted on
devtmpfs       devtmpfs          4.0M     0  4.0M   0% /dev
tmpfs          tmpfs             969M     0  969M   0% /dev/shm
tmpfs          tmpfs             388M  1.7M  386M   1% /run
/dev/sda2      btrfs              19G  5.0G   14G  27% /
/dev/sda2      btrfs              19G  5.0G   14G  27% /home
/dev/sda1      ext4              974M  172M  735M  19% /boot
tmpfs          tmpfs             969M  216K  968M   1% /tmp
tmpfs          tmpfs             194M  144K  194M   1% /run/user/1000
/dev/sr0       iso9660           1.9G  1.9G     0 100% /run/media/maminjie/Fedora-WS-Live-36-1-5
vmhgfs-fuse    fuse.vmhgfs-fuse  304G  110G  194G  37% /mnt/hgfs

df 的 -T 参数就可以显示文件系统的类型。

3)/etc/fstab 文件

[maminjie@fedora ~]$ cat /etc/fstab

#
# /etc/fstab
# Created by anaconda on Tue May 31 16:16:48 2022
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=89c63ae9-aecb-41dd-ba2f-dc750d94046c /                       btrfs   subvol=root,compress=zstd:1 0 0
UUID=cdb8d723-c331-4809-a62d-4fa54ee5c3b7 /boot                   ext4    defaults        1 2
UUID=89c63ae9-aecb-41dd-ba2f-dc750d94046c /home                   btrfs   subvol=home,compress=zstd:1 0 0

系统开机时会主动读取 /etc/fstab 这个文件中的内容,根据文件里面的配置挂载磁盘

3.6.3.2. superblock 信息
3.6.3.2.1. dumpe2fs

dumpe2fs 被用来查询 EXT 族文件系统中的 superblock信息。

简单用法:
dumpe2fs [-h] 设备文件名

选项与参数:
-h      仅列出 superblock 的数据,不会列出其它的区段内容

通过上一节我们知道 /dev/sda1 使用的是 ext4 文件系统,通过 dumpe2fs 查询如下:

[maminjie@fedora ~]$ sudo dumpe2fs /dev/sda1
dumpe2fs 1.46.5 (30-Dec-2021)
Filesystem volume name:   <none>            # 文件系统的名称(不一定会有)
Last mounted on:          /boot             # 上一次挂载的目录位置
Filesystem UUID:          cdb8d723-c331-4809-a62d-4fa54ee5c3b7
Filesystem magic number:  0xEF53            # 上方的 UUID 为 Linux 对设备的定义码
Filesystem revision #:    1 (dynamic)       # 下方的 features 为文件系统的特征数据
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Filesystem flags:         signed_directory_hash
Default mount options:    user_xattr acl    # 预设在挂载时会主动加上的挂载参数
Filesystem state:         clean             # 文件系统的状态,clean 是没问题
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              65536             # inode 的总数
Block count:              262144            # block 的总数
Reserved block count:     13107             # 保留的 block 总数
Overhead clusters:        12949
Free blocks:              205234            # 可用的 block 数量
Free inodes:              65087             # 可用的 inode 数量
First block:              0
Block size:               4096              # 单个 block 的容量大小
Fragment size:            4096
Group descriptor size:    64
Reserved GDT blocks:      127
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8192
Inode blocks per group:   512
Flex block group size:    16
Filesystem created:       Wed Jun  1 03:51:33 2022
Last mount time:          Tue May 31 21:11:04 2022
Last write time:          Tue May 31 21:11:04 2022
Mount count:              3
Maximum mount count:      -1
Last checked:             Wed Jun  1 03:51:33 2022
Check interval:           0 (<none>)
Lifetime writes:          278 MB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:	          256                   # inode 的容量大小
Required extra isize:     32
Desired extra isize:      32
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      201536cc-be9d-478d-b33a-8ee4a8a0b45b
Journal backup:           inode blocks
Checksum type:            crc32c
Checksum:                 0x8646f3be
Journal features:         journal_incompat_revoke journal_64bit journal_checksum_v3
Total journal size:       32M               # Journal 日志式数据的可供记录总容量
Total journal blocks:     8192
Max transaction length:   8192
Fast commit length:       0
Journal sequence:         0x000002da
Journal start:            1
Journal checksum type:    crc32c
Journal checksum:         0xbf8d0b75


Group 0: (Blocks 0-32767) csum 0x6fb8 [ITABLE_ZEROED]   # 第一块 block group 位置
  Primary superblock at 0, Group descriptors at 1-1     # 主要 superblock
  Reserved GDT blocks at 2-128
  Block bitmap at 129 (+129), csum 0x4fd8dc24
  Inode bitmap at 137 (+137), csum 0x22a4e70b
  Inode table at 145-656 (+145)                         # inode table
  28503 free blocks, 7747 free inodes, 12 directories, 7416 unused inodes
  Free blocks: 4265-32767                               # 底下两行说明剩余的容量
  Free inodes: 103, 111-438, 441, 444, 777-8192
Group 1: (Blocks 32768-65535) csum 0x4203 [ITABLE_ZEROED]
  Backup superblock at 32768, Group descriptors at 32769-32769
  Reserved GDT blocks at 32770-32896
  Block bitmap at 130 (bg #0 + 130), csum 0x31275ca2
  Inode bitmap at 138 (bg #0 + 138), csum 0x7b1c4465
  Inode table at 657-1168 (bg #0 + 657)
  32639 free blocks, 8188 free inodes, 4 directories, 8188 unused inodes
  Free blocks: 32897-65535
  Free inodes: 8197-16384
Group 2: (Blocks 65536-98303) csum 0x56dc [INODE_UNINIT, ITABLE_ZEROED]
...     # 后续为更多其它的 block group

dumpe2fs 显示的内容分为两部分:上半部是 superblock 内容,下半部是每个 block group 信息。/dev/sda1 规划的 block 为 4K,第一个 block 编号为 0,且 block group 内的所有信息都以 block 的编号来表示。下面介绍下 Group 0 内的信息:

  • Group 0 所占用的 block 编号从 0 到 32767,superblock 则在第 0 号的 blcok 区块内。
  • 文件系统描述说明在第 1 号 block 中。
  • block bitmap 与 inode bitmap 则在 129 和 137 号 block 上。
  • 至于 inode table 分布于 145-656 号 block 上。
  • 由于一个 inode 占用 256B,inode table 总共有 512(=656-145+1)个 block,每个 block 的大小为 4K。由这些可以算出 inode 的数量总共有 8192(=512*4096/256) 个。
  • 这个 Group 0 目前可用的 block 有 28503 个,可用的 inode 有 7747 个。
  • 剩余的 inode 号码为 103, 111-438, 441, 444, 777-8192。

4. 文件系统管理

文件系统与磁盘紧密关联,如果系统里面新增一个磁盘,大概可能会有下面一些动作需要做:

  • 对磁盘进行分区,以建立可用的 partition
  • 对该 partition 进行格式化,已建立系统可用的 filesystem
  • 对 filesystem 进行必要的检测
  • 在 Linux 系统上,建立挂载点,并将分区挂载上来。

4.1. 磁盘分区

一块磁盘可以被分区成多个分区槽(partition),比如 Windows 上,一颗磁盘可能被分成 C:,D:,E: 等盘符(槽),本节介绍 Linux 下磁盘是如何分区的。

4.1.1. 设备文件名

4.1.1.1. 磁盘命名

1)命名格式

  • /dev/sd[a-p]

    由于 SATA/USB/SAS 等磁盘接口都是使用 SCSI 模块来驱动的,因此这些接口的磁盘设备文件名都是 /dev/sd[a-p] 的格式。

  • /dev/vd[a-p]

    如果主机为虚拟机,对于 VirtIO 接口的磁盘,磁盘设备文件名采用 /dev/vd[a-p] 的格式。

2)命名顺序

由于 SATA/USB 接口的磁盘没有一定的顺序,命名是根据 Linux 核心侦测到磁盘的顺序进行命名的。

举例:假设 PC 上有两个 SATA 磁盘和一个 USB 磁盘,而主板上有六个 SATA 的插槽。这两个 STAT 磁盘分别安插在主板上的 SATA1,SATA5 插槽上,这三个磁盘在 Linux 中的设备文件名如下:

  • SATA1 插槽上的命名:/dev/sda
  • SATA5 插槽上的命名:/dev/sdb
  • USB 磁盘(开机完成后才被检测到)命名:/dev/sdc
4.1.1.2. 分区命名

如果一个磁盘被分区成两个分区槽,那么每个分区槽的设备文件名又是如何命名的呢?

下面主要介绍 MBR (Master Boot Record,主要开机记录区)的方式下的分区命名格式。

MBR 的分区分为:主要分区、延伸分区、逻辑分区。

  • 主要分区与延伸分区最多可以有四个(硬盘的限制);
  • 延伸分区最多只能有一个(操作系统的限制);
  • 逻辑分区是由延伸分区持续切割出来的分区槽;
  • 主要分区和逻辑分区可以格式化后作为数据存取的分区槽,延伸分区无法格式化;
  • 逻辑分区的数量依操作系统而不同,在 Linux 系统中 SATA 硬盘已经可以突破 63 个以上的分区限制。

假设磁盘设备文件名为 /dev/sda,则各分区命名格式如下:

  • 主要分区与延伸分区命名:/dev/sda[1-4]
  • 逻辑分区命名:/dev/sda[5-]

注意:逻辑分区槽的设备名称编号从 5 开始,因为前四个都是保留给主要分区和延伸分区的。

4.1.2. 分区挂载

所谓的挂载就是利用一个目录当成进入点,将磁盘分区槽的数据放置在该目录下,也就是说,进入该目录就可以读取该分区槽的意思。这个动作称为挂载,进入点的目录称为挂载点。

由于整个 Linux 系统最重要的是根目录,因此根目录一定需要挂载分区槽的。至于其的目录则可依用户自己的需求来挂载分区槽。以下图作说明:

上图中,假设磁盘被分为两个分区槽,partition 1 挂载到根目录,partition 2 挂载到 /home 目录。也就是说,当数据放在 /home 内的各子目录时,数据是防止到 partition 2 上的,如果不是放在 /home 底下的目录,那么数据就会被放置到 partition 1 上。

4.1.3. 分区状态

目前磁盘分区主要有 MBR 和 GPT 两种格式,这两种格式所使用的分区工具不一样。

4.1.3.1. lsblk 列出磁盘列表

lsblk(list block device,列出所有储存装置)命令可以列出系统上的所有磁盘列表。

简单用法:
lsblk [-dfimpt] [device]

选项与参数:
-d      仅列出磁盘本身,并不会列出该磁盘的分区数据
-f      同时列出该磁盘内的文件系统名称
-i      使用 ASCII 的线段输出,不使用复杂的编码(在某些环境下很有用)
-m      同时输出该装置在 /dev 底下的权限数据(rwx 数据)
-p      列出该装置的完成文件名,而不是仅列出最后的名字
-t      列出该磁盘装置的详细数据,包括磁盘队列机制、预读写的数据量大小等

范例一:列出本系统下的所有磁盘与磁盘内的分区信息

[maminjie@fedora home]$ lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda      8:0    0   20G  0 disk
├─sda1   8:1    0    1G  0 part /boot
└─sda2   8:2    0   19G  0 part /home
                                /
sr0     11:0    1  1.9G  0 rom  /run/media/maminjie/Fedora-WS-Live-36-1-5
zram0  252:0    0  1.9G  0 disk [SWAP]

sda 磁盘分了两个区,各列说明如下:

  • NAME:装置的文件名,会省略 /dev 等前导目录
  • MAJ:MIN:分别是主要:次要装置代码,系统通过这两个代码来识别装置
  • RM:是否为可卸除装置(removable device),如光盘、USB磁盘等
  • SIZE:容量
  • RO:是否为只读装置
  • TYPE:类型,分为:磁盘(disk)、分区槽(partition)、只读存储器(rom)等
  • MOUNTPOINTS:挂载点

范例二:仅列出 /dev/sda 装置内的所有数据的完整文件名

[maminjie@fedora home]$ lsblk -ip /dev/sda
NAME        MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
/dev/sda      8:0    0  20G  0 disk
|-/dev/sda1   8:1    0   1G  0 part /boot
`-/dev/sda2   8:2    0  19G  0 part /home
                                    /

范例三:在范例二基础上列出文件系统名称

[maminjie@fedora home]$ lsblk -ipf /dev/sda
NAME        FSTYPE FSVER LABEL                 UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
/dev/sda
|-/dev/sda1 ext4   1.0                         cdb8d723-c331-4809-a62d-4fa54ee5c3b7  734.5M    18% /boot
`-/dev/sda2 btrfs        fedora_localhost-live 89c63ae9-aecb-41dd-ba2f-dc750d94046c   13.9G    26% /home
                                                                                                   /

-f 除了列出文件系统名称,还列出了文件系统版本、标签、UUID、分区可用容量等。

4.1.3.2. blkid 列出装置的 UUID

UUID(Universally Unique Identifier,通用唯一识别码),Linux 会将系统内所有的装置都给予一个独一无二的标识符,这个标识符可以用于挂载或使用装置/文件系统。

[maminjie@fedora home]$ blkid
/dev/sda2: LABEL="fedora_localhost-live" UUID="89c63ae9-aecb-41dd-ba2f-dc750d94046c" UUID_SUB="37b329d1-44eb-4374-bc57-b2e2a81e7e2c" BLOCK_SIZE="4096" TYPE="btrfs" PARTUUID="37619dd2-02"
/dev/sr0: BLOCK_SIZE="2048" UUID="2022-05-04-21-36-58-00" LABEL="Fedora-WS-Live-36-1-5" TYPE="iso9660" PTUUID="7a218b9a" PTTYPE="dos"
[maminjie@fedora home]$ sudo blkid
/dev/sda2: LABEL="fedora_localhost-live" UUID="89c63ae9-aecb-41dd-ba2f-dc750d94046c" UUID_SUB="37b329d1-44eb-4374-bc57-b2e2a81e7e2c" BLOCK_SIZE="4096" TYPE="btrfs" PARTUUID="37619dd2-02"
/dev/sr0: BLOCK_SIZE="2048" UUID="2022-05-04-21-36-58-00" LABEL="Fedora-WS-Live-36-1-5" TYPE="iso9660" PTUUID="7a218b9a" PTTYPE="dos"
/dev/sda1: UUID="cdb8d723-c331-4809-a62d-4fa54ee5c3b7" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="37619dd2-01"
/dev/zram0: LABEL="zram0" UUID="e6136743-240d-4d41-b3f9-1af80e6bbce8" TYPE="swap"

备注:blkid 有用户权限限制。

4.1.3.3. parted 列出磁盘分区信息

虽然通过 lsblk 可以知道系统上的所有装置,通过 blkid 可以知道所有的文件系统,但还不清楚磁盘的分区类型,通过 parted 可以列出磁盘的分区表类型和分区信息。

简单用法:
parted device_name print

范例一:列出 /dev/sda 磁盘的相关数据

maminjie@fedora home]$ sudo parted /dev/sda print
Model: VMware, VMware Virtual S (scsi)      # 磁盘的模块名称(厂商)
Disk /dev/sda: 21.5GB                       # 磁盘的总容量
Sector size (logical/physical): 512B/512B   # 磁盘的每个逻辑/物理扇区容量
Partition Table: msdos                      # 分区表的格式(MBR/GPT等),msdos=MBR
Disk Flags:
                                            # 以下是分区数据
Number  Start   End     Size    Type     File system  Flags
 1      1049kB  1075MB  1074MB  primary  ext4         boot
 2      1075MB  21.5GB  20.4GB  primary  btrfs

备注:parted 有用户权限限制。

4.1.4. 分区制作

fdisk 命令用于创建 MBR 分区,gdisk 命令用于创建 GPT 分区。由于作者当前系统的磁盘是采用 MBR 分区的,下面主要介绍 fdisk 的操作,当然作者并不想真正的创建分区,只是介绍下 fdisk 的用法。

4.1.4.1. fdisk
[maminjie@fedora home]$ fdisk -h

Usage:
 fdisk [options] <disk>         change partition table
 fdisk [options] -l [<disk>...] list partition table(s)

Display or manipulate a disk partition table.

Options:
 -b, --sector-size <size>      physical and logical sector size
 -B, --protect-boot            don't erase bootbits when creating a new label
 -c, --compatibility[=<mode>]  mode is 'dos' or 'nondos' (default)
 -L, --color[=<when>]          colorize output (auto, always or never)
                                 colors are enabled by default
 -l, --list                    display partitions and exit
 -x, --list-details            like --list but with more details
 -n, --noauto-pt               don't create default partition table on empty devices
 -o, --output <list>           output columns
 -t, --type <type>             recognize specified partition table type only
 -u, --units[=<unit>]          display units: 'cylinders' or 'sectors' (default)
 -s, --getsz                   display device size in 512-byte sectors [DEPRECATED]
     --bytes                   print SIZE in bytes rather than in human readable format
     --lock[=<mode>]           use exclusive device lock (yes, no or nonblock)
 -w, --wipe <mode>             wipe signatures (auto, always or never)
 -W, --wipe-partitions <mode>  wipe signatures from new partitions (auto, always or never)

 -C, --cylinders <number>      specify the number of cylinders
 -H, --heads <number>          specify the number of heads
 -S, --sectors <number>        specify the number of sectors per track

 -h, --help                    display this help
 -V, --version                 display version

Available output columns:
 gpt: Device Start End Sectors Size Type Type-UUID Attrs Name UUID
 dos: Device Start End Sectors Cylinders Size Type Id Attrs Boot End-C/H/S Start-C/H/S
 bsd: Slice Start End Sectors Cylinders Size Type Bsize Cpg Fsize
 sgi: Device Start End Sectors Cylinders Size Type Id Attrs
 sun: Device Start End Sectors Cylinders Size Type Id Flags

For more details see fdisk(8).

简单用法:fdisk 设备名称

范例一:以 /dev/sda 为例介绍 fdisk 的操作

maminjie@fedora home]$ sudo fdisk /dev/sda
[sudo] password for maminjie:

Welcome to fdisk (util-linux 2.38-rc1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.


Command (m for help): m

Help:

  DOS (MBR)
   a   toggle a bootable flag
   b   edit nested BSD disklabel
   c   toggle the dos compatibility flag

  Generic
   d   delete a partition
   F   list free unpartitioned space
   l   list known partition types
   n   add a new partition
   p   print the partition table
   t   change a partition type
   v   verify the partition table
   i   print information about a partition

  Misc
   m   print this menu
   u   change display/entry units
   x   extra functionality (experts only)

  Script
   I   load disk layout from sfdisk script file
   O   dump disk layout to sfdisk script file

  Save & Exit
   w   write table to disk and exit
   q   quit without saving changes

  Create a new label
   g   create a new empty GPT partition table
   G   create a new empty SGI (IRIX) partition table
   o   create a new empty DOS partition table
   s   create a new empty Sun partition table


Command (m for help):

fdisk 不加任何选项将进入一个交互界面,所以不需要专门记 fdisk 的命令。

上面已经提示,当前磁盘正在使用,操作是危险的。

fdisk 只用需要 root 权限,此外,需要注意的是,装置名不能加上数字,这里是指整个磁盘装置,而不是某个分区。

1)p 打印磁盘分区表

Command (m for help): p

Disk /dev/sda: 20 GiB, 21474836480 bytes, 41943040 sectors
Disk model: VMware Virtual S
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x37619dd2

Device     Boot   Start      End  Sectors Size Id Type
/dev/sda1  *       2048  2099199  2097152   1G 83 Linux
/dev/sda2       2099200 41943039 39843840  19G 83 Linux

Command (m for help):

上半部分显示整体磁盘的状态,当前磁盘共有 20GB 左右的容量,共有 41943040 个扇区,每个扇区容量为 512 bytes。

下半部分显示每个分区的一些信息:

  • Device:分区设备文件名
  • Boot:是否作为启动区,* 表明是
  • Start:每一个分区槽的开始扇区号码位置
  • End:每一个分区槽的结束扇区号码位置,与 start 之间可以算出分区槽的总容量
  • Sectors:分区槽占用的扇区数
  • Size:分区槽的容量

从上面可知,整个磁盘已经不可以进行额外的分区了,最大扇区数为 41943040,最大号码 41943039 已经使用了。另外,新分区通常选用上一个分区的结束扇区号码数加 1 作为起始扇区号码。

2)w/q 退出操作

使用 fdisk 进行一些操作后,按下 q 所有的动作都不会生效,按下 w 所有的动作才生效,所以谨慎使用 w。

3)n 添加分区

Command (m for help): n

All space for primary partitions is in use.

Command (m for help):

由于所有空间都被用完了,所以没办法添加新的分区。读者如需要新增分区,可以根据命令提示或参考其它资料进行操作。

4)d 删除分区

Command (m for help): p

Disk /dev/sda: 20 GiB, 21474836480 bytes, 41943040 sectors
Disk model: VMware Virtual S
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x37619dd2

Device     Boot   Start      End  Sectors Size Id Type
/dev/sda1  *       2048  2099199  2097152   1G 83 Linux
/dev/sda2       2099200 41943039 39843840  19G 83 Linux

Command (m for help): d
Partition number (1,2, default 2):

Partition 2 has been deleted.

Command (m for help): p
Disk /dev/sda: 20 GiB, 21474836480 bytes, 41943040 sectors
Disk model: VMware Virtual S
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x37619dd2

Device     Boot Start     End Sectors Size Id Type
/dev/sda1  *     2048 2099199 2097152   1G 83 Linux

Command (m for help): q

输入 d 后选择要删除的分区编号,如果不选择将默认选择 default 提示的编号,这里作者不是真的删除,所以最后按 q 退出。

4.1.4.2. /proc/partitions

文件 /proc/partitions 记录系统的扇区信息。

[maminjie@fedora home]$ cat /proc/partitions
major minor  #blocks  name

  11        0    1970848 sr0
   8        0   20971520 sda
   8        1    1048576 sda1
   8        2   19921920 sda2
 252        0    1982464 zram0
4.1.4.3. partprobe

在分区新增或删除时,因为 Linux 此时还在使用这个磁盘,为了担心系统出问题,所以分区表并没有被更新。有两种方式来更新:重启、partprobe。

[maminjie@fedora home]$ partprobe -h
Usage: partprobe [OPTION] [DEVICE]...
Inform the operating system about partition table changes.

  -d, --dry-run    do not actually inform the operating system
  -s, --summary    print a summary of contents
  -h, --help       display this help and exit
  -v, --version    output version information and exit

When no DEVICE is given, probe all partitions.

Report bugs to <bug-parted@gnu>.

一般使用 partprobe -s 更跟新分区表。

4.2. 磁盘格式化

分区完后,就需要进行文件系统的格式化,格式化的指令是 mkfs(make filesystem),这个指令其实是个综合的指令,比如:mkdfs.xfs,mkfs.ext4 等。如下所示:

[maminjie@fedora home]$ mkfs
mkfs          mkfs.cramfs   mkfs.ext2     mkfs.ext4     mkfs.hfsplus  mkfs.msdos    mkfs.vfat
mkfs.btrfs    mkfs.exfat    mkfs.ext3     mkfs.fat      mkfs.minix    mkfs.ntfs     mkfs.xfs

输入 mkfs,然后连续按两次[tab],显示出当前支持 mkfs 命令。

4.2.1. mkfs

[maminjie@fedora home]$ mkfs -h

Usage:
 mkfs [options] [-t <type>] [fs-options] <device> [<size>]

Make a Linux filesystem.

Options:
 -t, --type=<type>  filesystem type; when unspecified, ext2 is used
     fs-options     parameters for the real filesystem builder
     <device>       path to the device to be used
     <size>         number of blocks to be used on the device
 -V, --verbose      explain what is being done;
                      specifying -V more than once will cause a dry-run
 -h, --help         display this help
 -V, --version      display version

For more details see mkfs(8).

mkfs -t ext4 相当于 mkfs.ext4。

4.2.2. mkfs.ext4

简单用法:
mkfs.ext4 [-b block-size] [-L volume-label] 设备名称

选项与参数:
-b      设定 block 的大小,有 1K,2K,4K 的容量
-L      后面接这个装置的标签名称(lsblk -f 可以显示出标签)

其它选项:

[maminjie@fedora home]$ mkfs.ext4 -h
mkfs.ext4: invalid option -- 'h'
Usage: mkfs.ext4 [-c|-l filename] [-b block-size] [-C cluster-size]
	[-i bytes-per-inode] [-I inode-size] [-J journal-options]
	[-G flex-group-size] [-N number-of-inodes] [-d root-directory]
	[-m reserved-blocks-percentage] [-o creator-os]
	[-g blocks-per-group] [-L volume-label] [-M last-mounted-directory]
	[-O feature[,...]] [-r fs-revision] [-E extended-option[,...]]
	[-t fs-type] [-T usage-type ] [-U UUID] [-e errors_behavior][-z undo_file]
	[-jnqvDFSV] device [blocks-count]

4.3. 文件系统检测

由于系统在运行时,可能会出现一些硬件或电源灯问题,从而导致文件系统发生错乱,下面主要介绍 ext4 文件系统的检测命令。检测的指令是 fsck(filesystem check),这个指令也是个综合的指令,比如:fsck.xfs,fsck.ext4 等。如下所示:

maminjie@fedora home]$ fsck
fsck          fsck.cramfs   fsck.ext2     fsck.ext4     fsck.hfs      fsck.minix    fsck.ntfs     fsck.xfs
fsck.btrfs    fsck.exfat    fsck.ext3     fsck.fat      fsck.hfsplus  fsck.msdos    fsck.vfat

4.3.1. fsck

[maminjie@fedora home]$ fsck -h
fsck from util-linux 2.38-rc1
fsck.ext4: invalid option -- 'h'
Usage: fsck.ext4 [-panyrcdfktvDFV] [-b superblock] [-B blocksize]
		[-l|-L bad_blocks_file] [-C fd] [-j external_journal]
		[-E extended-options] [-z undo_file] device

Emergency help:
 -p                   Automatic repair (no questions)
 -n                   Make no changes to the filesystem
 -y                   Assume "yes" to all questions
 -c                   Check for bad blocks and add them to the badblock list
 -f                   Force checking even if filesystem is marked clean
 -v                   Be verbose
 -b superblock        Use alternative superblock
 -B blocksize         Force blocksize when looking for superblock
 -j external_journal  Set location of the external journal
 -l bad_blocks_file   Add to badblocks list
 -L bad_blocks_file   Set badblocks list
 -z undo_file         Create an undo file

4.3.2. fsck.ext4

简单用法:
fsck.ext4 [-pf] [-b superblock] 设备名称

选项与参数:
-p      当文件系统在修复时,若有需要回复 y 的动作时,
        自动回复 y 来继续进行修复动作。
-f      强制检查!一般来说,如果 fsck 没有发现任何 unclean 的标志,
        不会主动进入检查,加上 -f 就强制进行检查。
-D      针对文件系统下的目录进行优化配置
-b      后面接 superblock 的位置!一般来说这个选项用不到。
        但是如果你的 superblock 因故损毁时,通过这个参数即可
        利用文件系统内备份的 superblock 来尝试救援。一般来说,
        superblock 备份在:
        - 1K block 放在 8193
        - 2K block 放在 16384
        - 4K block 放在 32768

其它选项:

[maminjie@fedora home]$ fsck.ext4 -h
fsck.ext4: invalid option -- 'h'
Usage: fsck.ext4 [-panyrcdfktvDFV] [-b superblock] [-B blocksize]
		[-l|-L bad_blocks_file] [-C fd] [-j external_journal]
		[-E extended-options] [-z undo_file] device

Emergency help:
 -p                   Automatic repair (no questions)
 -n                   Make no changes to the filesystem
 -y                   Assume "yes" to all questions
 -c                   Check for bad blocks and add them to the badblock list
 -f                   Force checking even if filesystem is marked clean
 -v                   Be verbose
 -b superblock        Use alternative superblock
 -B blocksize         Force blocksize when looking for superblock
 -j external_journal  Set location of the external journal
 -l bad_blocks_file   Add to badblocks list
 -L bad_blocks_file   Set badblocks list
 -z undo_file         Create an undo file

4.4. 文件系统挂载

在进行挂载前,需要确定几件事:

  • 单一文件系统不应该被重复挂载在不同的挂载点(目录)中;
  • 单一目录不应该重复挂载多个文件系统;
  • 要作为挂载点的目录,理论上应该都是空目录。

如果要挂载的目录并不是空的,那么挂载了文件系统之后,原目录中的内容会暂时消失,等到文件系统被卸载之后,原目录才又可见。

4.4.1. mount

简单用法:
mount -a
mount [-l]
mount [-t 文件系统类型] LABEL='' 挂载点
mount [-t 文件系统类型] UUID='' 挂载点
mount [-t 文件系统类型] 设备文件名 挂载点

选项与参数:
-a      依照配置文件 /etc/fstab 的数据将所有未挂载的磁盘都挂载上来
-l      单纯的输入 mount 会显示目前挂载的信息,加上 -l 可列出 label 名称
-t      可以加上文件系统类型来指定预挂载的类型。常见的 Linux 支持的类型有:
        xfs,ext3,ext4,reiserfs,vfat,iso9660(光盘格式),
        nfs,cifs,smbfs(后三种为网络文件系统)
-n      在默认的情况下,系统会将实际挂载的情况实时写入 /etc/mtab 中,供其它程序使用。
        但在某些情况下(例如单人维护模式)为了避免问题会刻意不写入,此时就使用 -n 选项。
-o      后面可以接一些挂载时额外加上的选项,比如账号、密码、读写权限等:
        async, sync:   此文件系统是否使用同步写入(sync)或异步(async)的内存机制。
        atime, noatime:是否修订文件的读取时间(atime)。为了性能,某些时刻会使用 noatime
        ro, rw:        挂载文件系统称为只读(ro)或可擦写(rw)
        auto, noauto:  允许此文件系统被以 mount -a 自动挂载
        dev, nodev:    是否允许此文件系统上可建立设备文件,dev 为允许
        suid, nosuid:  是否允许此文件系统含有 suid/sgid 的文件格式
        exec, noexec:  是否允许此文件系统上含有可行二进制文件
        user, nouser:  是否允许此文件系统让任何使用者执行 mount。一般来说,
                        mount 仅有 root 可以进行,但加上 user 参数,则可让
                        一般 user 也能够对此 partititon 进行 mount。
        defaults:      默认值为:rw,suid,dev,exec,auto,nouser,async
        remount:       重新挂载。这在系统出错或重新更新参数时,很有用。

mount 的更多用法如下:

[maminjie@fedora work]$ mount -h

Usage:
 mount [-lhV]
 mount -a [options]
 mount [options] [--source] <source> | [--target] <directory>
 mount [options] <source> <directory>
 mount <operation> <mountpoint> [<target>]

Mount a filesystem.

Options:
 -a, --all               mount all filesystems mentioned in fstab
 -c, --no-canonicalize   don't canonicalize paths
 -f, --fake              dry run; skip the mount(2) syscall
 -F, --fork              fork off for each device (use with -a)
 -T, --fstab <path>      alternative file to /etc/fstab
 -i, --internal-only     don't call the mount.<type> helpers
 -l, --show-labels       show also filesystem labels
 -m, --mkdir[=<mode>]    alias to '-o X-mount.mkdir[=<mode>]'
 -n, --no-mtab           don't write to /etc/mtab
     --options-mode <mode>
                         what to do with options loaded from fstab
     --options-source <source>
                         mount options source
     --options-source-force
                         force use of options from fstab/mtab
 -o, --options <list>    comma-separated list of mount options
 -O, --test-opts <list>  limit the set of filesystems (use with -a)
 -r, --read-only         mount the filesystem read-only (same as -o ro)
 -t, --types <list>      limit the set of filesystem types
     --source <src>      explicitly specifies source (path, label, uuid)
     --target <target>   explicitly specifies mountpoint
     --target-prefix <path>
                         specifies path used for all mountpoints
 -v, --verbose           say what is being done
 -w, --rw, --read-write  mount the filesystem read-write (default)
 -N, --namespace <ns>    perform mount in another namespace

 -h, --help              display this help
 -V, --version           display version

Source:
 -L, --label <label>     synonym for LABEL=<label>
 -U, --uuid <uuid>       synonym for UUID=<uuid>
 LABEL=<label>           specifies device by filesystem label
 UUID=<uuid>             specifies device by filesystem UUID
 PARTLABEL=<label>       specifies device by partition label
 PARTUUID=<uuid>         specifies device by partition UUID
 ID=<id>                 specifies device by udev hardware ID
 <device>                specifies device by path
 <directory>             mountpoint for bind mounts (see --bind/rbind)
 <file>                  regular file for loopdev setup

Operations:
 -B, --bind              mount a subtree somewhere else (same as -o bind)
 -M, --move              move a subtree to some other place
 -R, --rbind             mount a subtree and all submounts somewhere else
 --make-shared           mark a subtree as shared
 --make-slave            mark a subtree as slave
 --make-private          mark a subtree as private
 --make-unbindable       mark a subtree as unbindable
 --make-rshared          recursively mark a whole subtree as shared
 --make-rslave           recursively mark a whole subtree as slave
 --make-rprivate         recursively mark a whole subtree as private
 --make-runbindable      recursively mark a whole subtree as unbindable

For more details see mount(8).
4.4.1.1. 挂载不指定类型

mount 命令不加 -t 选项,系统会自动分析最恰当的文件系统来尝试挂载需要的设备。

由于文件系统机会都有 superblock,所以 Linux 通过分析 superblock 搭配 Linux 自己的驱动程序去测试挂载,如果测试成功,就立刻自动的使用该类型的文件系统进行挂载。主要参考下面两个文件:

  • /etc/filesystem:系统指定的测试挂载文件系统类型的优先级
  • /proc/filesystem:Linux 系统已经加载的文件系统类型
[maminjie@fedora work]$ cat /etc/filesystems
ext4
ext3
ext2
nodev proc
nodev devpts
iso9660
vfat
hfs
hfsplus
*

Linux 支持的文件系统的驱动程序都写在如下的目录中:

  • /lib/modules/$(uname -r)/kernel/fs
[maminjie@fedora work]$ ls /lib/modules/$(uname -r)/kernel/fs
9p                 cachefiles  ecryptfs  fat      hfsplus  minix       nilfs2    overlayfs     squashfs  vboxsf
affs               ceph        erofs     fscache  isofs    netfs       nls       pstore        sysv      xfs
afs                cifs        exfat     fuse     jffs2    nfs         ntfs3     reiserfs      ubifs     zonefs
befs               coda        ext4      gfs2     jfs      nfs_common  ocfs2     romfs         udf
binfmt_misc.ko.xz  dlm         f2fs      hfs      lockd    nfsd        orangefs  smbfs_common  ufs
4.4.1.2. 重新挂载根目录

整个目录树最重要的地方就是根目录了,所以根目录根本就不能被卸载。如果你的挂载参数要改变,或者是根目录出现只读状态时,如何重新挂载呢?

除了重启(reboot),也可以用下面的方法:

范例:将 / 重新挂载,并加入参数为 rw 与 auto
mount -o remount,rw,auto /
4.4.1.3. 挂载不特定目录

也可以利用 mount 来将某个目录挂载到另外一个目录上。这并不是挂载文件系统,而是额外挂载某个目录的方法!

[maminjie@fedora work]$ mkdir d1 d2
[maminjie@fedora work]$ ls -lid d1 d2
880 drwxrwxr-x. 1 maminjie maminjie 0 Jun 13 23:05 d1
881 drwxrwxr-x. 1 maminjie maminjie 0 Jun 13 23:05 d2
[maminjie@fedora work]$ sudo mount --bind d2 d1
mount: (hint) your fstab has been modified, but systemd still uses
       the old version; use 'systemctl daemon-reload' to reload.
[maminjie@fedora work]$ ls -lid d1 d2
881 drwxrwxr-x. 1 maminjie maminjie 0 Jun 13 23:05 d1
881 drwxrwxr-x. 1 maminjie maminjie 0 Jun 13 23:05 d2
[maminjie@fedora work]$ umount d1
umount: /home/maminjie/work/d1: must be superuser to unmount.
[maminjie@fedora work]$ sudo umount d1
[maminjie@fedora work]$ ls -lid d1 d2
880 drwxrwxr-x. 1 maminjie maminjie 0 Jun 13 23:05 d1
881 drwxrwxr-x. 1 maminjie maminjie 0 Jun 13 23:05 d2

实际上,mount --bind 还可以绑定两个文件。

4.4.1.4. 设置开机挂载

我们在开机后,进入 Linux 系统后,在执行 df 查看磁盘容量的时候,看到的一些设备已经被挂载了,而我们并没有去执行 mount 命令。实际上,这些都是在开机时自动挂载的。

在将开机挂载前,先来看看系统挂载的一些限制:

  • 根目录 / 是必须挂载的,而且一定要先于其它挂载点被挂载进来
  • 其它挂载点必须为已建立的目录,可任意指定,但一定要遵守文件系统层次标准(FHS)
  • 所有挂载点在同一时间之内,只能挂载一次
  • 所有 partition 在同一时间之内,只能挂载一次
  • 若进行卸载,必须先将工作目录移到挂载点(及其子目录)之外
4.4.1.4.1. /etc/fstab

若希望文件系统在开机时就挂载好,在 /etc/fstab 文件中配置就可以了。fstab(filesystem table)

[maminjie@fedora work]$ cat /etc/fstab

#
# /etc/fstab
# Created by anaconda on Tue May 31 16:16:48 2022
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=89c63ae9-aecb-41dd-ba2f-dc750d94046c /                       btrfs   subvol=root,compress=zstd:1 0 0
UUID=cdb8d723-c331-4809-a62d-4fa54ee5c3b7 /boot                   ext4    defaults        1 2
UUID=89c63ae9-aecb-41dd-ba2f-dc750d94046c /home                   btrfs   subvol=home,compress=zstd:1 0 0

该文件的内容共有六个字段,概括如下:

[设备/UUID等] [挂载点] [文件系统] [文件系系统参数] [dump] [fsck]

各字段介绍如下:

1)第一列:磁盘设备文件名/UUID/LABEL

这个字段可以的数据主要有三个:

  • 文件系统或磁盘的设备文件名,如:/dev/sda1
  • 文件系统的 UUID,如:UUID=xxx
  • 文件系统的 LABEL,如:LABEL=xxx

2)第二列:挂载点(mount point)

目录名

3)第三列:磁盘分区槽的文件系统

手动执行 mount 挂载时可以让系统自动测试挂载,这里必须写明确文件系统,包括:xfs,ext4,vfat,btrfs,nfs 等。

4)第四列:文件系统参数

同 mount 命令中的参数

5)第五列:是否被 dump 备份命令使用

dump 是一个用来做备份的命令,可以直接写 0

6)第六列:是否以 fsck 检测扇区

4.4.1.4.2. /etc/mtab

/etc/fstab 是开机是的配置文件,实际文件系统的挂载时记录到 /etc/mtab 与 /proc/mounts 这两个文件中。每次更改文件系统的挂载,也会同时更改这两个文件。

万一在 /etc/fstab 中输入的数据错误,导致无法顺利开机,在进入单人维护模式时,/ 将是只读的,也就无法修改 /etc/fstab,也无法更新 /etc/mtab。可以使用下面方法重新挂载根目录:

mount -n -o remount,rw /
4.4.1.5. 特殊LOOP设备挂载
4.4.1.5.1. 挂载光盘/DVD镜像文件
mkdir /xx/yy
mount -o loop /xxx/yyy.iso /xx/yy

访问目录 /xx/yy 就可以访问光盘或者DVD中的文件了。

4.4.1.5.2. 挂载大文件

可以制作一个大文件,然后将这个文件格式化后挂载。这个可以解决很多系统的分区不良情况。

举例来说,如果当初在分区时,你只分出一个根目录,假设没有多余的容量可以进行额外的分区了。偏偏根目录很大,这时就可以用这种方式,感觉就像多了一个分区槽。

4.4.1.5.2.1. 建立大型文件

dd 命令可以用来建立空的文件,用法如下:

[maminjie@fedora work]$ dd if=/dev/zero of=/home/maminjie/work/loopdev bs=1M count=128
128+0 records in
128+0 records out
134217728 bytes (134 MB, 128 MiB) copied, 1.53093 s, 87.7 MB/s
[maminjie@fedora work]$ ll -h loopdev
-rw-rw-r--. 1 maminjie maminjie 128M Jun 14 23:04 loopdev

上面命令的简单意义如下:

  • if:是 input file,输入文件,/dev/zero 是会一直输出 0 的设备
  • of:是 output file,将一堆 0 写入后面接的文件中
  • bs:是每个 block 大小,就像文件系统里的 block 一样
  • count:bs 的数量,bs * count 即是这个文件的容量
4.4.1.5.2.2. 格式化大型文件

通过 mkfs 系列命令对文件进行格式化,比如将文件格式化为 ext4 文件系统:

[maminjie@fedora work]$ mkfs.ext4 loopdev
mke2fs 1.46.5 (30-Dec-2021)
Discarding device blocks: done
Creating filesystem with 131072 1k blocks and 32768 inodes
Filesystem UUID: 29b4eef4-7016-4b0b-8f69-63d0cdf797a9
Superblock backups stored on blocks:
	8193, 24577, 40961, 57345, 73729

Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

[maminjie@fedora work]$ blkid loopdev
loopdev: UUID="29b4eef4-7016-4b0b-8f69-63d0cdf797a9" BLOCK_SIZE="1024" TYPE="ext4"
4.4.1.5.2.3. 挂载大型文件

利用 mount -o loop 进行挂载,如下:

[maminjie@fedora work]$ mkdir testfs
[maminjie@fedora work]$ sudo mount -o loop loopdev testfs
mount: (hint) your fstab has been modified, but systemd still uses
       the old version; use 'systemctl daemon-reload' to reload.
[maminjie@fedora work]$ df testfs
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/loop0        117203    14    108015   1% /home/maminjie/work/testfs
4.4.1.5.2.4. 卸载大型文件
[maminjie@fedora work]$ sudo umount testfs/
[maminjie@fedora work]$ df testfs
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/sda2       19921920 5364872  14377032  28% /home

4.4.2. umount

umount 将设备文件卸载

简单用法:
umount [-fn] 设备命名或挂载点

选项与参数:
-f      强制卸载!可用在类似网络文件系统(NFS)无法读取到的情况下
-l      立即卸载文件系统,比 -f 还强
-n      不更新 /etc/mtab 情况下卸载

umount 的更多用法如下:

[maminjie@fedora work]$ umount -h

Usage:
 umount [-hV]
 umount -a [options]
 umount [options] <source> | <directory>

Unmount filesystems.

Options:
 -a, --all               unmount all filesystems
 -A, --all-targets       unmount all mountpoints for the given device in the
                           current namespace
 -c, --no-canonicalize   don't canonicalize paths
 -d, --detach-loop       if mounted loop device, also free this loop device
     --fake              dry run; skip the umount(2) syscall
 -f, --force             force unmount (in case of an unreachable NFS system)
 -i, --internal-only     don't call the umount.<type> helpers
 -n, --no-mtab           don't write to /etc/mtab
 -l, --lazy              detach the filesystem now, clean up things later
 -O, --test-opts <list>  limit the set of filesystems (use with -a)
 -R, --recursive         recursively unmount a target with all its children
 -r, --read-only         in case unmounting fails, try to remount read-only
 -t, --types <list>      limit the set of filesystem types
 -v, --verbose           say what is being done
 -q, --quiet             suppress 'not mounted' error messages
 -N, --namespace <ns>    perform umount in another namespace

 -h, --help              display this help
 -V, --version           display version

For more details see umount(8).

4.5. 磁盘/文件系统参数修订

某些时刻,你可能希望修改一下目前文件系统的一些相关信息。举例来说,你可能要修改 Label name,或者是 journal 的参数,或者其它磁盘/文件系统运作是的相关参数。

4.5.1. mknod

在 Linux 底下所有的设备都以文件来代表,但是那个文件如何代表该设备呢?实际上是通过文件的 major 与 minor 数值来替代的。

/dev/sda 的相关设备代码如下:

[maminjie@fedora work]$ ll /dev/sda*
brw-rw----. 1 root disk 8, 0 Jun 13 20:32 /dev/sda
brw-rw----. 1 root disk 8, 1 Jun 13 20:32 /dev/sda1
brw-rw----. 1 root disk 8, 2 Jun 13 20:32 /dev/sda2

上面的 8 位主要设备代码(Major),而 0-2 为次要设备代码(Minor)。常见的磁盘文件名的设备代码如下所示:

磁盘文件名MajorMinor
/dev/sda80-15
/dev/sdb816-31
/dev/loop070
/dev/lopp171

mknod 命令可用来修订 Major 和 Minor。

简单用法:
mknod 设备文件名 [bcp] [Major] [Minor]

选项与参数:
设备种类:
b       设定设备名称成为一个周边存储设备文件,比如磁盘等
c       设定设备名称成为一个周边输入设备文件,比如鼠标/键盘等
p       设定设备名称成为一个 FIFO 文件
Major   主要设备代码
Minor   次要设备代码

mknod 的更多用法如下:

maminjie@fedora work]$ mknod --help
Usage: mknod [OPTION]... NAME TYPE [MAJOR MINOR]
Create the special file NAME of the given TYPE.

Mandatory arguments to long options are mandatory for short options too.
  -m, --mode=MODE    set file permission bits to MODE, not a=rw - umask
  -Z                   set the SELinux security context to default type
      --context[=CTX]  like -Z, or if CTX is specified then set the SELinux
                         or SMACK security context to CTX
      --help     display this help and exit
      --version  output version information and exit

Both MAJOR and MINOR must be specified when TYPE is b, c, or u, and they
must be omitted when TYPE is p.  If MAJOR or MINOR begins with 0x or 0X,
it is interpreted as hexadecimal; otherwise, if it begins with 0, as octal;
otherwise, as decimal.  TYPE may be:

  b      create a block (buffered) special file
  c, u   create a character (unbuffered) special file
  p      create a FIFO

NOTE: your shell may have its own version of mknod, which usually supersedes
the version described here.  Please refer to your shell's documentation
for details about the options it supports.

GNU coreutils online help: <https://www.gnu/software/coreutils/>
Full documentation <https://www.gnu/software/coreutils/mknod>
or available locally via: info '(coreutils) mknod invocation'

4.5.2. tune2fs

tune2fs 可以修改 ext4 的 label name 和 UUID

简单用法:
tune2fs [-l] [-L label] [-U uuid] 设备文件名

选项与参数:
-l      类似 dumpe2fs -h 的功能,将 superblock 内的数据读出来
-L      修改 label name
-U      修改 UUID

范例一:列出 /dev/sda1 的 label name

[maminjie@fedora work]$ sudo tune2fs -l /dev/sda1 | grep name
Filesystem volume name:   <none>

没有命名,可以通过sudo tune2fs -L LABELNAME /dev/sda1 修改 label name。

4.6. 内存置换空间

内存置换空间(swap,交换区),可以用在内存不足的时候,为了让后续的程序可以顺利的运作,将内存中暂不使用的程序与数据挪到 swap 中,让内存空出来给需要执行的程序加载。

现在由于内存都很大,因此在个人机上,不设定 swap 问题也不大。但对于服务器,最好还是预留一些 swap 来缓冲一下系统的内存用量,至少是备而不用。

如果系统已经创建好了,发现没有创建 swap,不要慌,可以用如下的方式创建 swap:

  • 设定一个 swap 分区
  • 建立一个虚拟内存的文件

4.6.1. 使用实体分区槽创建swap

  1. 分区:使用分区命令 fdisk/gdisk 在磁盘中分出一个分区槽作为 swap。
  2. 格式化:使用mkswap 设备文件名将分区槽格式化成 swap 格式
  3. 启动:使用swapon 设备文件名启动 swap 设备
  4. 观察:使用 free 与 swapon -s 观察内存的用量
  5. 停止:使用swapoff 设备文件名停止 swap 设备

4.6.2. 使用文件创建swap

  1. 创建文件:使用 dd 命令创建文件
  2. 格式化:使用mkswap 文件名将文件格式化成 swap 格式
  3. 启动:使用swapon 文件名启动 swap 设备
  4. 观察:使用 free 与 swapon -s 观察内存的用量
  5. 停止:使用swapoff 文件名停止 swap 设备

5. 文件系统原理

Linux 文件系统原理

6. 参考

  • 鸟哥Linux私房菜-基础篇
  • Linux 系统目录结构
  • Linux-5.10源代码之文件系统简介
  • Linux 内核中的文件系统

本文标签: 文件系统Linux