发布于 2026-01-06 0 阅读
0

由 Mux 呈现的“一切皆文件 DEV 全球展示与讲述挑战赛:展示你的项目!”

一切皆文件

由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!

UNIX 和类 UNIX 操作系统的一个显著特征是“一切皆文件”[ 1 ]。* 从操作系统的角度来看,文档、目录、链接、输入输出设备等等,都只是字节流的接收器或源[ 2 ]。您可以使用以下命令验证目录实际上是一种特殊的文件:

$ view /etc
Enter fullscreen mode Exit fullscreen mode

/etc这将显示文件(目录)的内容。请注意,这是以只读模式view运行的简写[ 7 ],因此您可以通过输入`--readonly`来退出。以文件形式打开目录时务必格外小心——如果您不小心编辑了不应该编辑的内容,可能会对系统造成严重损坏。在Linux文件系统中,` /etc/ `目录包含表示设备的文件,`/etc/`目录包含表示进程和系统信息的特殊文件,等等:vivi -R:q!/dev/proc

$ ls -l /dev/std*
lrwxrwxrwx 1 root 15 Nov  3  2017 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root 15 Nov  3  2017 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root 15 Nov  3  2017 /dev/stdout -> /proc/self/fd/1

$ cat /proc/uptime  # shows current system uptime
36710671.21 1127406622.14

$ cat /dev/random  # returns randomly-generated bytes
{IGnh▒I侨▒▒Ұ>j▒L▒▒%▒=▒▒U@▒Q▒2▒;▒l▒q▒$▒r▒1▒U񝾎...
Enter fullscreen mode Exit fullscreen mode

其他常见的/dev文件包括/dev/zero会持续生成零流的 `null` 文件,以及/dev/null接受所有输入但不做任何处理的 `null` 文件(可以把它想象成一个垃圾桶)[ 8 ]。需要注意的是,“文件”每次打开时可能显示相同的信息,也可能不断变化——反映系统的当前状态,或显示某些持续运行进程的结果。

但是为什么在 UNIX 系统中一切都是文件呢?

正如 Dennis Ritchie 和 Ken Thompson 在他们 1974 年发表于 ACM 通讯的论文《UNIX 分时系统》中所概述的那样,“一切皆文件”方法有三个主要优点:

  1. 文件和设备 I/O 尽可能相似
  2. 文件名和设备名具有相同的语法和含义,因此,需要文件名作为参数的程序也可以传递设备名。
  3. 特殊文件(/dev/random例如 .txt 文件等)与普通文件一样,都受到相同的保护机制。

这种方法的优势在贝尔实验室 1982 年的这段视频中得到了说明。视频中,AWK 编程语言的创建者和 UNIX 的共同创建者 Brian Kernighan 描述了如何通过流水线方式处理程序,以减少不必要的代码重复(通过模块化)并提高灵活性(跳转到 05:30):


$ makewords sentence | lowercase | sort | unique | mismatch
Enter fullscreen mode Exit fullscreen mode

上面重现了 Kernighan 输入的代码。这段代码makewords将文本文件分割sentence成单词(以空格分隔),并按行返回一个单词。makewords它接收一个文件作为输入,其输出通常会发送到终端,但我们将其通过管道(使用 `or` )传递|给下一个方法lowercase。`or`lowercase将每一行视为一个单独的参数,将所有大写字母转换为小写字母,然后将其输出通过管道传递给 `sort` sort,后者按字母顺序对单词列表进行排序。`sort`sort将其输出通过管道传递给 `declude` unique,后者从列表中删除重复单词,并将其输出传递给mismatch`check`,后者将唯一的、全部小写的单词列表与字典文件进行比对。默认情况下,任何拼写错误的单词(字典中未出现的单词)都会打印到终端。通过连接这五个独立的函数,我们轻松地创建了一个全新的拼写检查函数。

请注意,输入可以来自普通文件,也可以来自磁盘等特殊文件以及其他输入设备,例如终端本身。输出可以发送到终端、其他程序,或者以文件的形式写入磁盘。这种将函数流水线化处理、对文件、磁盘和特殊 I/O 设备一视同仁的能力,极大地增强了 UNIX 相对于其他区别对待这些设备的系统的功能和灵活性。


更准确的说法是“一切皆文件描述符或进程”[ 3 ]。(文件描述符有时也称为“句柄”。)文件描述符本质上是指向文件、目录、输入输出设备等的非负索引[ 5stdin ]。例如,`file`、`file` 、 `file`stdout和 ` file` 的文件描述符stderr分别为 0、1 和 2。因此,当我们想要抑制错误输出时,我们会将其重定向(使用>命令 [ 4 ])到/dev/null`file` 。

$ command 2>/dev/null
Enter fullscreen mode Exit fullscreen mode

我们可以使用 `|&` 将特定命令的所有输出(` stdout&&` stderr)作为另一个命令的输入2>&1 |,或者更简单地使用 `'|&'` [ 6 ]:

$ command1 2>&1 | command2
$ command1 |& command2
Enter fullscreen mode Exit fullscreen mode

操作系统使用inode(索引节点)将文件描述符映射到文件(磁盘上字节的实际位置)[ 10 ]。

进程[ 9 ]与文件描述符是分离的。进程是程序的一个实例,它当前正在执行。进程包含待执行代码的映像(只读副本)、执行期间使用的内存和堆空间、相关的文件描述符等等。进程还有自己独立的索引系统(进程ID pid)。


有关的:

Linux 简介 (2008),Machtelt Garrels

UNIX进程入门(2014),布莱恩·斯托蒂

UNIX 过去的幽灵:设计模式的历史探寻(2010),尼尔·布朗

unix-history-repo(从 1970 年至今的连续 UNIX 提交历史记录)

文章来源:https://dev.to/awwsmm/everything-is-a-file-3oa