[译] 在 UNIX 中,一切皆文件

为了有计划的发展架构设计、界面、文化和开发路线,UNIX 系统明确了一系列统一的概念和创想。这几点里面最重要的一点莫过于一句咒语:「一切皆文件」,被普遍认为是 UNIX 的定义之一。mysql

最主要的设计原则是提供一个访问大范围输入/输出资源(包括文件、文件夹、硬盘、CD-ROM、调制解调器、键盘、打印机、显示器、终端机甚至跨进程和网络通信)的统一的范例。窍门是提供一个全部这些资源的抽象对象,UNIX 之父把这个对象叫作「文件」。由于每一个「文件」都由同一个 API[1]暴露,因此你能够用同一套命令来读写/操做磁盘、键盘、文件或网络设备。git

这个基本概念有两种含义:程序员

  • 在 UNIX 中,一切都是字节流
  • 在 UNIX 中,文件系统被用做通用的命名空间

在 UNIX 中,一切都是字节流

在 UNIX 中,文件是由什么组成的呢?文件其实和一系列可读写的字节没什么区别。若是你有一个文件的索引(咱们称之为「文件描述符[2]」),那么 UNIX 的 I/O 通道就已经准备好了,他们有着一样的一套操做和 API —— 不管设备的类型如何、底层硬件是什么。github

纵观历史,UNIX 是第一个把 I/O 抽象成一个统一的概念和一系列原语的系统。那时,大部分操做系统为每一种或一类设备提供不一样的 API。一些早期的微型计算机操做系统甚至须要你使用多个命令去拷贝文件 —— 由于每一个命令对应指定的软盘大小!sql

对于大多数程序员和用户来讲,UNIX 向他们暴露了:shell

  • 硬盘中的文件服务器

  • 文件夹网络

  • 连接架构

  • 大容量存储设备(例如:硬盘、CD-ROM、磁带、USB 设备)tcp

  • 跨进程通讯(例如:管线、共享内存、UNIX 套接字)

  • 网络通讯

  • 可交互终端

  • 几乎其余全部设备(例如:打印机、显卡)

对于字节流这种形式你能够:

  • read(读)
  • write(写)
  • lseek(指针移动)
  • close(关闭)

统一的 API 特性对于 UNIX 程序来讲是基础也是很是有效的:在 UNIX 中你能够很很轻松地编写一个处理文件的程序,由于不须要关心文件是存储在本地磁盘中、储存在远程网络驱动器上、在互联网中传播、经过用户互动输入,仍是经过其余程序在内存中生成。这显著下降了程序的复杂性、减缓了开发者的学习曲线。而且,UNIX 架构的这个基础特性也让程序组合到一块儿很是简单(你只须要传输两个特殊的文件:标准输入和标准输出)。

最后请注意,当全部的文件提供一致的 API 时,一些特殊类型的设备可能会不支持某些操做。举个很明显的例子,你不能够在鼠标设备上使用 lseek命令,或在 CD-ROM 设备上使用 write命令(假设你的 CD 是只读的)。

文件系统有通用命名空间

在 UNIX 里,文件不只仅是有一致 API 的字节流,并且能够被统一的方式索引:文件系统有着通用命名空间。

全局命名空间和挂载机制

UNIX 的文件系统路径为标签资源提供了一致的全局方案,从而能够忽略他们的物理地址。举几个例子,你可使用 /usr/local命令访问一个本地文件夹、/home/joe/memo.pdf命令访问一个文件、/mnt/cdrom命令访问 CD-ROM、/usr命令访问网络驱动器上的一个文件夹、/dev/sda1命令访问硬盘分区、/tmp/mysql.sock命令访问 UNIX 域名套接字、/dev/tty0命令访问终端,甚至使用 /dev/mouse命令来访问鼠标。这些通用命名空间一般看起来像一个文件层级或文件夹,其实就像前面举的例子,这些只是一个方便的抽象概念,一个文件路径能够引用一切东西:一个文件系统、一个设备、一个网络共享或信道。

命名空间是分层的,全部的资源均可以从根文件夹(/)访问到。你可使用一样的命名空间来访问多个文件系统:你只是在命名空间的指定的位置(好比 /backups)「链接」了一个设备或文件系统(好比外置硬盘)。用 UNIX 术语来讲,这个操做叫作 挂载mounting)一个文件系统,你链接文件系统的命名空间位置叫作 挂载点mount point)。你能够经过给挂载的文件系统中的全部资源添加以挂载点命名的前缀,就像访问通用命名空间的一部分同样,来访问它的全部资源(好比 /backups/myproject-Oct07.zip这个文件)。

当不一样的资源会被明显覆盖的状况下,我刚刚描述的挂载机制在创建一个统一的、明确的命名空间时就相当重要。对比一下这种命名空间和微软操做系统中的文件系统命名空间 —— MS-DOS 和 Windows 把设备视为文件可是 不会把文件系统放在通用命名空间中,它的命名空间是分区的而且每一个物理存储地址被视为独特的实体[3]C:\是第一个硬盘,E:\是 CD-ROM 设备等等。

伪文件系统

早期,UNIX 由于提供全局 API 以及将设备挂载到统一的文件系统命名空间的特性,大幅提高了输入/输出资源的集成度。这个方法是如此成功,以致于从那时开始有一种将更多资源和系统服务暴露为文件系统全局命名空间的趋势。Plan 9 是这种作法的先驱,而如今全部新的 UNIX 系统都这么作了。

这种方法致使产生了许多 伪文件系统,这些系统看起来和通常的文件系统同样,可是能够存取没有直接关联传统文件系统的资源。好比你可使用伪文件系统来查询控制进程、存取内核内部或创建 TCP 链接。这些伪文件系统具备文件系统语义,能够展现分层信息,并为大部分对象提供了统一存取的方式。伪文件系统有时也被称为虚拟文件系统,特色是没有物理设备也没有备份存储器,只依靠内存来工做。

伪文件系统的例子:

  • procfs(/proc):proc 文件系统包含一个特殊文件层,这个文件层能够用来查询或控制运行中的进程,或经过标准文件入口(大部分基于文本)一窥内核内部文件。
  • devfs(/devor /devices):devfs 将全部系统中的设备以动态文件系统命名空间呈现。devfs 也能够经过内核设备驱动直接管理这些命名空间和接口,以此来提供智能的设备管理 —— 包括设备入口注册/反注册。
  • tmpfs(/tmp):临时文件系统的内容会在重启时消失,tmpfs 是为速度和效率而设计的,具备动态文件系统大小、用以空间清理的显式回退等特性。
  • portalfs(/p):经过 BSD 门户文件系统,你能够将一个服务器进程链接到文件系统通用命名空间上。这样能够提供明确的经过文件系统对网络服务的存取过程。好比一个 App 能够经过打开一个合规的文件 /p/tcp/ph7spot.com/smtp来和 ph7spot.com上的 SMTP 服务器进行交互。门户文件系统很神奇,由于它在文件系统中能够提供套接字语义,还能够被 UNIX 系统工具传输和使用(好比:catgrepawk等等)—— 甚至能够经过 shell 来使用!
  • ctfs(/system/contract):协定文件系统做为一个以文件为基础的接口的 Solaris 协定子系统。Solaris 协定为各类各样的事件和失败状况定义了一个进程或进程组的表现形式 —— 好比,进程中止时重启。 Solaris 协定为诸如群集故障转移软件,批处理排队系统和网格计算引擎等环境中的软件管理和监视提供了很是高级的功能。

可以经过文件系统语义进行管理的系统资源究竟涉及多么大的范围,上面的例子可让你对有一个清楚的认识了。

结论

在现代的 UNIX 操做系统中,全部设备和大部分进程间通讯在文件系统层级都以文件或伪文件的形式查看和管理。「一切皆文件」的 UNIX 基础愿景和设计原则,是 UNIX 成功和长久的关键因素。它提供了一个有力、简单的抽象,使得系统、工具和社区能够在其之上创建。更重要的是它用一种专有的方式来解决问题,那就是为连接工具和应用提供了强有力的集成和基础组合机制。

尽管「一切皆文件」这个比喻很成功,可是一些人或多或少怀疑它的广泛性。当每一个文件都被视为字节流时,产生的一个后果就是元数据缺乏标准支持:为了合适地处理一个文件,每一个应用必须想办法计算文件类型、架构和语义。而且,为了保存元数据,每一个处理数据流的工具必须保持元数据不变(好比照片中的 XMP 信息)。所以,尽管 UNIX 文件的一大堆字节的形态对于连接文字界面的程序极度高效,同时也严重限制了多媒体和二进制应用的组合。

尽管它有它的限制,但不少人也认可这个比喻的影响力,和它在操做系统一体化上的效果。自从 UNIX 第一次发布以来,研究者们持续推动这一中心思想。好比 Plan 9 操做系统倡导一个将系统资源彻底集成的方法:Plan 9 愿景的基础就是这样的目标 —— 不只仅设备和信道,而是将 全部系统接口经过文件系统表明。好比 Plan 9 的设计人员注意到在 UNIX 中,网络设备不能 彻底地被视为合格的文件:它们经过套接字存取,而套接字有特有的打开语义而且属于一个不一样的命名空间(因特网套接字的主机和端口)。Plan 9 实现而且证实了,你能够在一个全局命名空间里成功的统一全部本地和远程设备。这个想法最终以 portalfs的形式在 UNIX 中实现。

其余来源于 Plan 9 的创新的概念也是基于「UNIX 中,一切皆文件」原则建立的。好比 Plan 9 在统一命名空间设计之上提供了另外一个抽象层:文件系统命名空间能够被每一个用户、每一个进程自定义,甚至动态调整[4]。最后,Plan 9 证实了「UNIX 中,一切皆文件」这个比喻,能够被在更大的层面上实现。事实上,这个基础概念在现代 UNIX 操做系统中正被继续发扬光大[5]

参考文献

  • 一本了不得的书 —— 《The Art of UNIX Programming》,Eric S. Raymond 著。
  • 《The Elements of Operating-System Style》和《Problems in the Design of UNIX》两章对本文有很大帮助。
  • 《10 Things I Hate About (U)NIX》,David Chisnall 著。
  • 「Linux 情报项目」中的挂载定义。
  • Wikipedia 上的 《UNIX File Types》。
  • 《Understanding UNIX Concepts》,USAIL (UNIX System Administration Independent Learning) 著。
  • 《文件系统层级标准》。
  • 《proc 文件系统》,Redhat 出品。
  • 《BSD 系统下的模块化用户模式文件系统》。
  • 《Self-Healing in Modern Operating Systems》,Michael W 著。帮你更深刻地理解 Solaris 协议子系统。

做者:Wy_连接:https://juejin.im/post/5b652d346fb9a04fc03129e6来源:掘金著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。

相关文章
相关标签/搜索