Linux文件体系
Linux以文件的形式对计算机中的数据和硬件资源进行管理,也就是彻底的一切皆文件,反映在Linux的文件类型上就是:普通文件、目录文件(也就是文件夹)、设备文件、链接文件、管道文件、套接字文件(数据通信的接口)等等。而这些种类繁多的文件被Linux使用目录树进行管理, 所谓的目录树就是以根目录(/)为主,向下呈现分支状的一种文件结构。不同于纯粹的ext2之类的文件系统,我把它称为文件体系,一切皆文件和文件目录树的资源管理方式一起构成了Linux的文件体系,让Linux操作系统可以方便使用系统资源。
所以文件系统比文件体系涵盖的内容少很多,Linux文件体系主要在于把操作系统相关的东西用文件这个载体实现:文件系统挂载在操作系统上,操作系统整个系统又放在文件系统里。但本文中文件体系的相关内容不是很多,大部分地方都可以用文件系统代替文件体系。
Linux中的文件类型
那就先简单说说Linux中的文件类型,主要关注普通文件、目录文件和符号连接文件。
-
普通文件(-)
- 从Linux的角度来说,类似mp4、pdf、html这样应用层面上的文件类型都属于普通文件
- Linux用户可以根据访问权限对普通文件进行查看、更改和删除
-
目录文件(d,directory file)
- 目录文件对于用惯Windows的用户来说不太容易理解,目录也是文件的一种
- 目录文件包含了各自目录下的文件名和指向这些文件的指针,打开目录事实上就是打开目录文件,只要有访问权限,你就可以随意访问这些目录下的文件(普通文件的执行权限就是目录文件的访问权限),但是只有内核的进程能够修改它们
- 虽然不能修改,但是我们能够通过vim去查看目录文件的内容
-
符号链接(l,symbolic link)
-
这种类型的文件类似Windows中的快捷方式,是指向另一个文件的间接指针,也就是我们常说的软链接
ln [-s -v] SRC DEST 硬链接: 1、只能对文件创建,不能应用于目录; 2、不能跨文件系统; 3、创建硬链接会增加文件被链接的次数; 符号链接: 1、可应用于目录; 2、可以跨文件系统; 3、不会增加被链接文件的链接次数; 4、其大小为指定的路径所包含的字符个数;
-
-
块设备文件(b,block)和字符设备文件(c,char)
- 这些文件一般隐藏在/dev目录下,在进行设备读取和外设交互时会被使用到
- 比如磁盘光驱就是块设备文件,串口设备则属于字符设备文件
- 系统中的所有设备要么是块设备文件,要么是字符设备文件,无一例外
-
FIFO(p,pipe)
- 管道文件主要用于进程间通讯。比如使用mkfifo命令可以创建一个FIFO文件,启用一个进程A从FIFO文件里读数据,启动进程B往FIFO里写数据,先进先出,随写随读。
-
套接字(s,socket)
- 用于进程间的网络通信,也可以用于本机之间的非网络通信
- 这些文件一般隐藏在/var/run目录下,证明着相关进程的存在
Linux目录树
对Linux系统和用户来说,所有可操作的计算机资源都存在于目录树这个逻辑结构中,对计算机资源的访问都可以认为是目录树的访问。就硬盘来说,所有对硬盘的访问都变成了对目录树中某个节点也就是文件夹的访问,访问时不需要知道它是硬盘还是硬盘中的文件夹。
目录树的逻辑结构也非常简单,就是从根目录(/)开始,不断向下展开各级子目录。
文件系统概述
- 为了能在磁盘分区设备上储存与读取文件,我们需要在分区上创立文件系统
- 每一个文件系统在Linux里都被解释成由一个根目录为起点的目录树结构
- Linux将各个文件系统挂载(mount)在系统目录树中使用。
- 对应不同的操作系统与设备,计算机里有许许多多种文件系统。不同的文件系统存放、搜索文件的方式都有不同。
文件系统类型
- Linux文件系统:
- ext2(Extended file system):适用于那些分区容量不是太大,更新也不频繁的情况,例如 /boot 分区
- ext3:是 ext2 的改进版本,其支持日志功能,能够帮助系统从非正常关机导致的异常中恢复。它通常被用作通用的文件系统
- ext4:是 ext 文件系统的最新版。提供了很多新的特性,包括纳秒级时间戳、创建和使用巨型文件(16TB)、最大1EB的文件系统,以及速度的提升
- xfs:SGI,支持最大8EB的文件系统
- btrfs(Oracle), reiserfs, jfs(AIX), swap
- 光盘:iso9660
- Windows:FAT32, NTFS,exFAT
- Unix:FFS(fast), UFS(unix), JFS2
- 网络文件系统:NFS, CIFS
- 集群文件系统:GFS2, OCFS2(oracle)
- 分布式文件系统:fastdfs,ceph, moosefs, mogilefs, glusterfs, Lustre
- RAW:未经处理或者未经格式化产生的文件系统
文件系统分类
- 根据其是否支持"journal"功能:
- 日志型文件系统: ext3, ext4, xfs, …
- 非日志型文件系统: ext2, vfat
- 文件系统的组成部分:
- 内核中的模块:ext4, xfs, vfat
- 用户空间的管理工具:mkfs.ext4, mkfs.xfs,mkfs.vfat
- Linux的虚拟文件系统:VFS
- 查前支持的文件系统:cat /proc/filesystems
- 查前目前的文件系统:lsblk -f
基于inode的文件系统
我们知道Linux操作系统支持很多不同的文件系统,比如ext2、ext3、XFS、FAT等等,而Linux把对不同文件系统的访问交给了VFS(虚拟文件系统),VFS能访问和管理各种不同的文件系统。所以有了区之后就需要把它格式化成具体的文件系统以便VFS访问。
标准的Linux文件系统Ext2是使用基于inode的文件系统
- 我们知道一般操作系统的文件数据除了文件实际内容外, 还带有很多属性,例如 Linux 操作系统的文件权限(rwx)与文件属性(拥有者、群组、 时间参数等),文件系统通常会将属性和实际内容这两部分数据分别存放在不同的区块
- 在基于inode的文件系统中,权限与属性放置到 inode 中,实际数据放到 data block 区块中,而且inode和data block都有编号
Ext2 文件系统在此基础上
- 文件系统最前面有一个启动扇区(boot sector)
- 这个启动扇区可以安装开机管理程序, 这个设计让我们能将不同的引导装载程序安装到个别的文件系统前端,而不用覆盖整个硬盘唯一的MBR, 也就是这样才能实现多重引导的功能
- 把每个区进一步分为多个块组 (block group),每个块组有独立的inode/block体系
- 如果文件系统高达数百 GB 时,把所有的 inode 和block 通通放在一起会因为 inode 和 block的数量太庞大,不容易管理
- 这其实很好理解,因为分区是用户的分区,实际计算机管理时还有个最适合的大小,于是计算机会进一步的在分区中分块
- (但这样岂不是可能出现大文件放不了的问题?有什么机制善后吗?)
- 每个块组实际还会分为分为6个部分,除了inode table 和 data block外还有4个附属模块,起到优化和完善系统性能的作用
所以整个分区大概会这样划分:
inode table
- 主要记录文件的属性以及该文件实际数据是放置在哪些block中,它记录的信息至少有这些:
- 大小、真正内容的block号码(一个或多个)
- 访问模式(read/write/excute)
- 拥有者与群组(owner/group)
- 各种时间:建立或状态改变的时间、最近一次的读取时间、最近修改的时间
- 没有文件名!文件名在目录的block中!
- 一个文件占用一个 inode,每个inode有编号
- Linux 系统存在 inode 号被用完但磁盘空间还有剩余的情况
- 注意,这里的文件不单单是普通文件,目录文件也就是文件夹其实也是一个文件,还有其他的也是
- inode 的数量与大小在格式化时就已经固定了,每个inode 大小均固定为128 bytes (新的ext4 与xfs 可设定到256 bytes)
- 文件系统能够建立的文件数量与inode 的数量有关,存在空间还够但inode不够的情况
- 系统读取文件时需要先找到inode,并分析inode 所记录的权限与使用者是否符合,若符合才能够开始实际读取 block 的内容
- inode 要记录的资料非常多,但偏偏又只有128bytes , 而inode 记录一个block 号码要花掉4byte ,假设我一个文件有400MB 且每个block 为4K 时, 那么至少也要十万条block 号码的记录!inode 哪有这么多空间来存储?为此我们的系统很聪明的将inode 记录block 号码的区域定义为12个直接,一个间接, 一个双间接与一个三间接记录区
data block
- 放置文件内容数据的地方
- 在格式化时block的大小就固定了,且每个block都有编号,以方便inode的记录
- 原则上,block 的大小与数量在格式化完就不能够再改变了(除非重新格式化)
- 在Ext2文件系统中所支持的block大小有1K, 2K及4K三种,由于block大小的区别,会导致该文件系统能够支持的最大磁盘容量与最大单一文件容量各不相同:
- Block 大小 1KB 2KB 4KB
- 最大单一档案限制 16GB 256GB 2TB
- 最大档案系统总容量 2TB 8TB 16TB
- 每个block 内最多只能够放置一个文件的资料,但一个文件可以放在多个block中(大的话)
- 若文件小于block ,则该block 的剩余容量就不能够再被使用了(磁盘空间会浪费)
- 所以如果你的档案都非常小,但是你的block 在格式化时却选用最大的4K 时,可能会产生容量的浪费
- 既然大的block 可能会产生较严重的磁碟容量浪费,那么我们是否就将block 大小定为1K ?这也不妥,因为如果block 较小的话,那么大型档案将会占用数量更多的block ,而inode 也要记录更多的block 号码,此时将可能导致档案系统不良的读写效能
- 事实上现在的磁盘容量都太大了,所以一般都会选择4K 的block 大小
superblock
- 记录整个文件系统相关信息的地方,一般大小为1024bytes,记录的信息主要有:
- block 与inode 的总量
- 未使用与已使用的inode / block 数量
- 一个valid bit 数值,若此文件系统已被挂载,则valid bit 为0 ,若未被挂载,则valid bit 为1
- block 与inode 的大小 (block 为1, 2, 4K,inode 为128bytes 或256bytes);
- 其他各种文件系统相关信息:filesystem 的挂载时间、最近一次写入资料的时间、最近一次检验磁碟(fsck) 的时间
- Superblock是非常重要的, 没有Superblock ,就没有这个文件系统了,因此如果superblock死掉了,你的文件系统可能就需要花费很多时间去挽救
- 每个块都可能含有superblock,但是我们也说一个文件系统应该仅有一个superblock 而已,那是怎么回事?事实上除了第一个块内会含有superblock 之外,后续的块不一定含有superblock,而若含有superblock则该superblock主要是做为第一个块内superblock的备份,这样可以进行superblock的救援
Filesystem Description
- 文件系统描述
- 这个区段可以描述每个block group的开始与结束的block号码,以及说明每个区段(superblock, bitmap, inodemap, data block)分别介于哪一个block号码之间
block bitmap
- 块对照表
- 如果你想要新增文件时要使用哪个block 来记录呢?当然是选择「空的block」来记录。那你怎么知道哪个block 是空的?这就得要通过block bitmap了,它会记录哪些block是空的,因此我们的系统就能够很快速的找到可使用的空间来记录
- 同样在你删除某些文件时,那些文件原本占用的block号码就得要释放出来, 此时在block bitmap 中对应该block号码的标志位就得要修改成为「未使用中」
inode bitmap
- 与block bitmap 是类似的功能,只是block bitmap 记录的是使用与未使用的block 号码, 至于inode bitmap 则是记录使用与未使用的inode 号码
目录树的读取过程
首先我们要知道
- 每个文件(不管是一般文件还是目录文件)都会占用一个inode
- 依据文件内容的大小来分配一个或多个block给该文件使用
- 创建一个文件后,文件完整信息分布在3处地方,生成2个新文件:
- 文件名记录在该文件所在目录的目录文件的block中,没有新文件生成
- 文件属性、权限信息、记录具体内容的block编号记录在inode中,inode是新生成文件
- 文件具体内存记录在block中,block是新生成文件
- 因为文件名的记录是在目录的block当中,「新增/删除/更名文件名」与目录的w权限有关
所以在Linux/Unix中,文件名称只是文件的一个属性,叫别名也好,叫绰号也罢,仅为了方便用户记忆和使用,但系统内部并不需要用文件名来定为文件位置,这样处理最直观的好处就是,你可以对正在使用的文件改名,换目录,甚至放到废纸篓,都不会影响当前文件的使用,这在Windows里是无法想象的。比如你打开个Word文件,然后对其进行重命名操作,Windows会告诉你门儿都没有,关闭文件先!但在Mac里就毫无压力,因为Mac的操作系统同样采用了inode的设计。
创建文件过程
当在ext2下建立一个一般文件时, ext2 会分配一个inode 与相对于该文件大小的block 数量给该文件
- 例如:假设我的一个block 为4 Kbytes ,而我要建立一个100 KBytes 的文件,那么linux 将分配一个inode 与25 个block 来储存该文件
- 但同时请注意,由于inode 仅有12 个直接指向,因此还要多一个block 来作为区块号码的记录
创建目录过程
当在ext2文件系统建立一个目录时(就是新建了一个目录文件),文件系统会分配一个inode与至少一块block给该目录
- inode记录该目录的相关权限与属性,并记录分配到的那块block号码
- 而block则是记录在这个目录下的文件名与该文件对应的inode号
- block中还会自动生成两条记录,一条是.文件夹记录,inode指向自身,另一条是…文件夹记录,inode指向父文件夹
从目录树中读取某个文件过程
- 因为文件名是记录在目录的block当中,因此当我们要读取某个文件时,就一定会经过目录的inode与block ,然后才能够找到那个待读取文件的inode号码,最终才会读到正确的文件的block内的资料。
- 由于目录树是由根目录开始,因此操作系统先通过挂载信息找到挂载点的inode号,由此得到根目录的inode内容,并依据该inode读取根目录的block信息,再一层一层的往下读到正确的文件。
举例来说,如果我想要读取/etc/passwd 这个文件时,系统是如何读取的呢?
先看一下这个文件以及有关路径文件夹的信息:
$ ll -di / /etc /etc/passwd
128 dr-xr-x r-x . 17 root root 4096 May 4 17:56 /
33595521 drwxr-x r-x . 131 root root 8192 Jun 17 00:20 /etc
36628004 -rw-r-- r-- . 1 root root 2092 Jun 17 00:20 /etc/passwd
于是该文件的读取流程为:
- /的inode:
- 通过挂载点的信息找到inode号码为128的根目录inode,且inode规定的权限让我们可以读取该block的内容(有r与x)
- /的block:
- 经过上个步骤取得block的号码,并找到该内容有etc/目录的inode号码(33595521)
- etc/的inode:
- 读取33595521号inode得知具有r与x的权限,因此可以读取etc/的block内容
- etc/的block:
- 经过上个步骤取得block号码,并找到该内容有passwd文件的inode号码(36628004)
- passwd的inode:
- 读取36628004号inode得知具有r的权限,因此可以读取passwd的block内容
- passwd的block:
- 最后将该block内容的资料读出来
挂载、卸载文件系统
挂载
mount命令
用途:挂载文件系统、ISO镜像到指定文件夹
格式:mount [ -t 类型 ] 存储设备(硬盘分区、U盘、光盘设备等) 挂载点目录
mount -o loop ISO镜像文件 挂载点目录
卸载
umount命令
用途:卸载已挂载的文件系统
格式:umount 存储设备位置
umount 挂载点目录
ISO镜像文件挂载示例
- 光驱托盘操作
- 弹出光驱:eject
- 收回光驱:eject -t
[root@localhost ~]# mkdir /media/fedora
[root@localhost ~]# mount -o loop F10-i686-Live.iso /media/fedora
[root@localhost ~]# ls /media/fedora
EFI GPL isolinux LiveOS README
设置自动挂载示例
- 每次重新开机后,能够自动完成挂载
- 将/dev/sdb1分区挂载到/mailbox目录
[root@localhost ~]# vi /etc/fstab
/dev/sdb1 /mailbox ext4 default 0 0
[root@localhost ~]# mount /dev/sdb1
[root@localhost ~]# mount | tail -1
/dev/sdb1 on /mailbox type ext4 (rw)
[root@localhost ~]# umount /mailbox
- /etc/fstab配置文件
- 包含了需要开机后自动挂载的文件系统记录
[root@localhost ~]# vi /etc/fstab
/dev/VolGroup00/LogVol00 / ext4 defaults 1 1
LABEL=/boot /boot ext4 defaults 1 2
devpts /dev/pts devpts gid=5,mode=620 0 0
tmpfs /dev/shm tmpfs defaults 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
/dev/VolGroup00/LogVol01 swap swap defaults 0 0
设备位置 挂载点 文件系统类型