# 文件系统

## Linux 文件系统

{% hint style="info" %}
不是进程的一切都是文件
{% endhint %}

这意味着打印机、扫描仪、终端屏幕、任何进程的代码——这些都是文件。你在文件系统上的文件是一串字节连接在一起创建的有意义的内容。

{% hint style="info" %}
文件只是一个数据流
{% endhint %}

目录也是文件，它们简单地包含当前目录中存在的文件和目录列表，就像一棵树。这样做的美妙之处在于你可以"打开"一个目录文件来查看其内容：

```bash
$ vim .
" ====================================================================
" Netrw Directory Listing                                 (netrw v168)
"   /Users/user/folder
"   Sorted by name
"   Quick Help: <F1>:help  -:go up dir  D:delete  R:rename  s:sort-by
"   x:special
" ===================================================================
../
./
another_folder/
some_file.txt
some_folder/
```

这就是UNIX存储当前目录的方式。它包含当前目录中的文件和目录列表。

## inode（索引节点）

![](https://drawings.jvns.ca/drawings/inodes.svg)

要拥有文件系统，你需要一个结构来管理它。文件系统不仅包含数据，还包含关于这些数据的一些信息，称为`元数据`（metadata）。这包括数据存储在哪里、谁拥有它以及谁可以看到它。这就是`inode`的作用——一个用于文件元数据的数据结构。

```bash
$ ls -li
total 0
287009 drwxr-xr-x   9 user  staff  288 23 Oct 07:36 another_folder
286999 -rw-r--r--   1 user  staff  110  9 Oct 11:37 some_file.txt
287002 drwxr-xr-x   5 user  staff  256 23 Sep 11:46 some_folder
```

每个文件都有一个唯一的`inode编号`（上面第一列）是文件存在时的唯一标识符。

### stat 命令

你可以使用`stat`命令来查看这个元数据：

```bash
$ stat -LF some_folder
drwxr-xr-x 8 user staff 256 Feb 05 13:37:00 2021 some_folder
```

* `drwxr-xr-x` 是文件权限
* `8` 是硬链接计数
* `user staff` 是用户和组名；文件和目录的所有权基于创建它们的用户的默认 uid（用户ID）和 gid（组ID）
* `256` 是文件大小，即文件中的字节数
* `Feb 05 13:37:00 2021` 是最后修改日期

## 文件权限

每个文件都有相关的权限，总共12个权限位：

![](/files/0BjVaCltNHlYBJX6QV4x)

### setuid 位（设置用户ID位）

{% hint style="info" %}
`setuid` 位对目录没有影响
{% endhint %}

`setuid` 位允许可执行文件以文件所有者的权限运行，而不是以启动它的用户权限运行。例如，如果一个可执行文件设置了`setuid`位并且由root拥有，那么当以普通用户身份启动时，它将以root权限运行。

一个设置了`setuid`权限的可执行文件示例是`passwd`，你可以使用它来更改登录密码。你可以使用`ls`命令来验证：

```bash
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 54256 Mar 26  2019 /usr/bin/passwd
```

你可以通过在"user"部分的执行位`x`位置看到`s`来识别`setuid`位的存在（见上面的命令输出）。

`s` 意味着执行位已设置，否则你会看到大写的`S`。这发生在`setuid`位已设置但执行位未设置时，向用户显示不一致：如果执行位未设置，`setuid`位无效。

### setgid 位（设置组ID位）

{% hint style="info" %}
`setgid` 位对文件和目录都有影响
{% endhint %}

设置`setgid`位的文件以拥有该文件的组的权限执行。换句话说，进程组ID将与文件相同。

当`setgid`用于目录时，在该目录中创建的文件将由父目录组拥有，而不是由创建它们的用户拥有。这通常用于简化文件共享（文件可以被属于特定组的所有用户修改）。

```bash
$ ls -l some_folder
drwxrwsr-x 1 user staff 256 Feb 6 04:37 some_folder
```

你可以通过在"group"部分的执行位`x`位置看到`s`来识别`setgid`位的存在（见上面的命令输出）。

`s` 意味着执行位已设置，否则你会看到大写的`S`。这发生在`setgid`位已设置但执行位未设置时，向用户显示不一致：如果执行位未设置，`setgid`位无效。

### sticky 位（粘滞位）

{% hint style="info" %}
`sticky` 位对文件没有影响
{% endhint %}

当`sticky`位用于目录时，该目录中的所有文件只能由其所有者修改。

使用`sticky`位的典型情况涉及`/tmp`目录。通常它对系统上的所有用户都可写，因此为了防止一个用户删除另一个用户的文件，设置了sticky位：

它通常对系统上的所有用户都可写，因此设置`sticky`位以防止一个用户修改或删除另一个用户的文件：

```bash
$ ls -ld /tmp
drwxrwxrwt 2 root wheel 64 Feb 7 08:50 /tmp
```

你可以通过在"other"部分的执行位`x`位置看到`t`来识别`sticky`位的存在（见上面的命令输出）。

`t` 意味着执行位已设置，否则你会看到大写的`T`。这发生在`sticky`位已设置但执行位未设置时，向用户显示不一致：如果执行位未设置，`sticky`位无效。

### rwx 权限

对于文件：

* `r` 可以读取（read）
* `w` 可以写入（write）
* `x` 可以执行（execute）

对于目录大致是：

* `r` 可以列出文件
* `w` 可以创建文件
* `x` 可以`cd`进入和修改文件

### 条目类型

然而，如果你查看元数据：

```bash
$ stat -LF
crw--w---- 1 user tty 16,2 Feb  7 09:29:10 2021 (stdin)
```

你会发现权限字符串`crw--w----`包含10个字符。第一个是特殊的条目类型字符，描述文件类型：

* `b` - 块特殊文件（block special file）
* `c` - 字符特殊文件（character special file）
* `d` - 目录（directory）
* `l` - 符号链接（symbolic link）
* `s` - 套接字链接（socket link）
* `p` - FIFO（命名管道）
* `-` - 普通文件（regular file）

### chmod 命令

你可以使用`chmod`工具来更改文件权限。在后端，`chmod`与文件的inode交互。

由于你需要3位来表示每个权限，你可以将其转换为整数并传递给`chmod`，例如：

```bash
$ chmod 721 .
# 或者 rwx-w---x
# 或者所有者拥有所有权限，组拥有写入权限，其他人拥有执行权限
```

`setuid`、`setgid`和`sticky`位分别用值`4`、`2`和`1`表示，例如：

```bash
# 在目录上设置setgid位
$ chmod 2775 .
```

更多使用示例参见[此处](https://github.com/cdxiaodong/cheat-sheets-cn/blob/master/Linux/console-commands.md#chmod)

你也可以限制自己的访问，移除自己的所有读取、写入和执行权限。如果文件元数据存储在文件本身中，你将无法再次更改权限（因为你无法写入文件）。这就是inode很酷的另一个原因：它们总是可以被文件所有者和root修改，所以你可以恢复你的权限。

## 文件链接

硬链接（Hard links）和符号链接（Symbolic links）是链接到硬盘驱动器上文件的两种不同方法。这些方法是文件系统的一部分，定义了文件及其位置。

![](/files/xmbXZkuZMpKCCmOBoF9g)

### 硬链接

`硬链接`是指向同一文件的两个文件名（你可以将它们视为文件别名）。例如，`.`和`..`是系统上当前目录和父目录的硬链接。

使用`ln`创建硬链接：

```bash
$ ls -li
total 0
1637699 -rw-r--r--  1 user  wheel  0 Feb  7 10:03 a

# 创建x作为a的硬链接
$ ln a x

$ ls -li
total 0
1637699 -rw-r--r--  2 user  wheel  0 Feb  7 10:03 a
1637699 -rw-r--r--  2 user  wheel  0 Feb  7 10:03 x
```

注意两个文件具有相同的inode编号。修改`x`或`a`都会更改同一个文件。

### 符号链接

`符号链接`是从一个位置到另一个位置的链接。符号链接是一个新文件，与原始文件分开，链接到原始文件。

使用`ln`创建符号链接：

```bash
$ ls -li
total 0
1637699 -rw-r--r--  1 user  wheel  0 Feb  7 10:03 a

# 创建y作为a的符号链接
$ ln -s a y

$ ls -li
total 0
1637699 -rw-r--r--  2 user  wheel  0 Feb  7 10:03 a
1638321 lrwxr-xr-x  1 user  wheel  1 Feb  7 10:09 y -> a
```

`y`是一个符号链接，是一个新的小文件（见大小为1）。修改`y`会更改`a`。

## 文件结构

文件系统可以被视为树状数据结构。每个节点（inode）都有指向其父节点、自身和所有子节点的指针。这形成了目录结构。

![](/files/kyAIg0YuFX99z6ZMmWST)

## 总结

* 文件系统使用inode构建
* inode在文件系统上是唯一的
* 用户是文件属性的一部分；此信息存储在inode中
* 多个文件系统可以被挂载并抽象为一个逻辑树

## 参考资料

* [How Unix Works: Become a Better Software Engineer](https://neilkakkar.com/unix.html) - 深入了解UNIX工作原理
* [Julia's Drawings: Unix permissions](https://drawings.jvns.ca/permissions/) - UNIX权限的可视化解释
* [How to use special permissions: the setuid, setgid and sticky bits](https://linuxconfig.org/how-to-use-special-permissions-the-setuid-setgid-and-sticky-bits) - 特殊权限的使用指南


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook.cdxiaodong.life/linux-an-quan/overview/file.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
