> For the complete documentation index, see [llms.txt](https://linux-in-action.gitbook.io/project/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://linux-in-action.gitbook.io/project/wen-jian-xi-tong.md).

# 文件系统

## 常见 Linux 目录

| 目录     | 用途                             |
| ------ | ------------------------------ |
| /      | 虚拟目录的根目录。通常不会在这里存储文件           |
| /bin   | 二进制目录，存放许多用户级的GNU工具            |
| /boot  | 启动目录，存放启动文件                    |
| /dev   | 设备目录，Linux在这里创建设备节点            |
| /etc   | 系统配置文件目录                       |
| /home  | 主目录，Linux在这里创建用户目录             |
| /lib   | 库目录，存放系统和应用程序的库文件              |
| /media | 媒体目录，可移动媒体设备的常用挂载点             |
| /mnt   | 挂载目录，另一个可移动媒体设备的常用挂载点          |
| /opt   | 可选目录，常用于存放第三方软件包和数据文件          |
| /proc  | 进程目录，存放现有硬件及当前进程的相关信息          |
| /root  | root用户的主目录                     |
| /sbin  | 系统二进制目录，存放许多GNU管理员级工具          |
| /run   | 运行目录，存放系统运作时的运行时数据             |
| /srv   | 服务目录，存放本地服务的相关文件               |
| /sys   | 系统目录，存放系统硬件信息的相关文件             |
| /tmp   | 临时目录，可以在该目录中创建和删除临时工作文件        |
| /usr   | 用户二进制目录，大量用户级的GNU工具和数据文件都存储在这里 |
| /var   | 可变目录，用以存放经常变化的文件，比如日志文件        |

## 文件的权限

### 文件权限符&#x20;

可以使用 `ls` 命令来查看 Linux 系统上的文件、目录和设备的权限。

```
gackle@machine:/Projects/cpp$ ls -l
total 392
-rwxrwxrwx 1 gackle gackle   4630 Jun 21 15:11 backend.md
-rwxrwxrwx 1 gackle gackle    764 Jun 21 15:17 main.cpp
-rwxrwxrwx 1 gackle gackle 224256 Jun 21 15:17 main.exe
-rwxrwxrwx 1 gackle gackle   9112 Jun 21 15:15 main_linux.exe
-rwxrwxrwx 1 gackle gackle 149686 Jun 21 15:17 main.obj
```

其中: 1. 输出结果的第一个字段就是**描述文件和目录权限的编码**。 2. 这个字段的第一个字符代表了对象的类型：

* \- 代表文件
* d 代表目录
* l 代表链接
* c 代表字符型设备
* b 代表块设备
* n 代表网络设备
  1. 之后有 3 组 三字符的编码，每一组定义了 3 种访问权限：
* r 代表对象是可读的
* w 代表对象是可写的
* x 代表对象是可执行的
* 若没有某种权限，该权限位会出现**单破折线**
  1. 3 组权限分别对应对象的 3 个安全级别：
* 对象的属主
* 对象的属组
* 系统其他用户

Linux 采用复杂的位系统来判定文件和目录的访问权限。每个文件都有三个安全等级：文件的属主、能够访问文件的默认属组以及系统上的其他用户。每个安全等级通过三个访问权限位来定义：读取、写入以及执行，对应于符号 `rwx`。如果某种权限被拒绝，权限对应的符号会用*单破折线*代替（比如 `r--` 代表只读权限）。

### 文件权限码&#x20;

| 权限  | 二进制值 | 八进制值 | 描述       |
| --- | ---- | ---- | -------- |
| --- | 000  | 0    | 没有任何权限   |
| --x | 001  | 1    | 只有执行权限   |
| -w- | 010  | 2    | 只有写入权限   |
| -wx | 011  | 3    | 有写入和执行权限 |
| r-- | 100  | 4    | 只有读取权限   |
| r-x | 101  | 5    | 有读取和执行权限 |
| rw- | 110  | 6    | 有读取和写入权限 |
| rwx | 111  | 7    | 有全部权限    |

## Linux 基本文件系统

Linux 初采用的是一种简单的文件系统，它模仿了Unix文件系统的功能。

### 1. ext 文件系统

Linux 操作系统中引入的早的文件系统叫作**扩展文件系统**（extended filesystem，简记为 ext）。 它为 Linux 提供了一个基本的类 Unix 文件系统：使用虚拟目录来操作硬件设备，在物理设备上按定长的块来存储数据。

ext 文件系统采用名为 **索引节点** 的系统来存放虚拟目录中所存储文件的信息。

索引节点系统在每个物理设备中创建一个单独的表（称为索引节点表）来存储这些文件的信息。存储在虚拟目录中的每一个文件在索引节点表中都有一个条目。

ext 文件系统名称中的 `extended` 部分来自其跟踪的每个文件的额外数据，包括：

* 文件名
* 文件大小
* 文件的属主
* 文件的属组
* 文件的访问权限
* 指向存有文件数据的每个硬盘块的指针

Linux通过唯一的数值（称作**索引节点号**）来引用索引节点表中的每个索引节点，这个值是 创建文件时由文件系统分配的。文件系统通过索引节点号而不是文件全名及路径来标识文件。

### 2. ext2 文件系统

最早的 ext 文件系统有不少限制，比如文件大小不得超过 2GB。ext2 文件系统是 ext 文件系统基本功能的一个扩展，但保持了同样的结构。ext2 文件系统扩展了索引节点表的格式来保存系统上每个文件的更多信息。

主要的区别在于：

1. ext2 的索引节点表为文件添加了*创建时间值*、*修改时间值* 和 *最后访问时间值* 来帮助系统管理员追踪文件的访问情况。
2. ext2 文件系统将允许的大文件大小增加到了2TB（在ext2的后期版本中增加到了32TB），以容纳数据库服务器中常见的大文件。
3. 除了扩展索引节点表外，ext2 文件系统还改变了文件在数据块中存储的方式：由于 ext 文件系统会导致数据存储“碎片化”的问题。因此 ext2 文件系统保存文件时，通过按组分配磁盘块来减轻碎片化。通过将数据块分组，文件系统在读取文件时不需要为了数据块查找整个物理设备。&#x20;

## Linux 日志文件系统

一直以来，ext 文件系统都是 Linux 发行版默认的文件系统，但由于存储或更新文件时需要用新信息更新索引节点表，这个操作也并非一气呵成。因此如果这个过程中出现系统崩溃或断电，二者内容就不同步了，即使文件存到了物理设备，ext2 甚至都不知道（如果索引表没有更新）。

**日志文件系统** 为 Linux 系统增加了一层安全性。它不再使用之前先将数据直接写入存储设备再更新索引节点表的做法，而是先将文件的更改写入到临时文件（称作 **日志**，journal）中。在数据成功写到存储设备和索引节点表之后，再删除对应的日志条目。

下面是目前日志文件系统的实现思路：

| 方法   | 描述                                             |
| ---- | ---------------------------------------------- |
| 数据模式 | 索引节点和文件都会被写入日志；丢失数据风险低，但性能差                    |
| 有序模式 | 只有索引节点数据会被写入日志，但只有数据成功写入后才删除；在性能和安全性之间取得了良好的折中 |
| 回写模式 | 只有索引节点数据会被写入日志，但不控制文件数据何时写入；丢失数据风险高，但仍比不用日志好   |

下面是一些常见的 Linux 日志文件系统：

### 3. ext3 文件系统

ext3 文件系统采用和 ext2 文件系统相同的索引节点结构，但给每个存储设备增加了一个日志文件，以将准备写入存储设备的数据先记入日志。

默认情况下，ext3 文件系统用 **有序模式** 的日志功能，可以在创建文件系统时将其改为数据模式或回写模式。

ext3 提供了基本的日志功能，但它： 1. 无法恢复误删除的文件 2. 没有任何内建的数据压缩功能（需要单独安装补丁） 3. 不支持加密文件

### 4. ext4 文件系统

ext4 是目前大多数流行的 Linux 发行版采用的默认文件系统，除了支持数据压缩和加密，还支持一个称作 **区段**（extent）的特性。

区段在存储设备上按块分配空间，但在索引节点表中只保存起始块的位置。由于无需列出所有用来存储文件中数据的数据块，它可以在索引节点表中节省一些空间。

ext4 还引入了 **块预分配技术**（block preallocation）。如果你想在存储设备上给一个你知道要变大的文件预留空间，ext4 文件系统可以为文件分配所有需要用到的块，而不仅仅是那些现在已经用到的块。ext4 文件系统用 0 填满预留的数据块，不会将它们分配给其他文件。

## 写时复制文件系统

就文件系统而言，日志式的另一种选择时一种叫做 **写时复制**（copy-on-wirte，COW）的技术。COW 利用**快照**兼顾了安全性和性能。如果要修改数据，会使用克隆或可写快照。修改过的数据并不会直接覆盖当前数据，而是被放入文件系统中的另一个位置。即便是数据修改该已经完成，之前的就数据也不会被重写。
