外行对“一切都是文件”的解释-与Windows有何不同?


36

我知道“一切都是文件”意味着即使设备在Unix和类似Unix的系统中也具有其文件名和路径,并且这允许在各种资源上使用通用工具,而不论其性质如何。但是我无法与Windows进行对比,Windows是我使用过的唯一其他操作系统。我已经阅读了一些有关此概念的文章,但我认为对于非开发人员而言,有些不容易理解。外行的解释是人们所需要的!

例如,当我要将文件复制到读卡器附带的CF卡时,将使用类似

zcat name_of_file > /dev/sdb

我认为在Windows中,读卡器将作为驱动程序出现,我们会做类似的事情。那么,“一切都是文件”哲学在这里有何不同?


2
听起来您好像已经了解了外行的解释。
詹姆斯·恢复莫妮卡·波克(Monica Polk)

不完全是,我想通过与MS Windows进行比较来了解它的好处。而且我没有得到有关进程间通信的部分。
Mohamed Ahmed 2014年

从该示例来看,您还不太了解文件系统如何工作。除非name_of_file碰巧是正确的文件系统映像,否则您只是破坏了CF卡...
Shadur 2014年

1
@Shadur是的,这是一个文件系统映像,请参见wiki.ipfire.org/en/installation/…–
Mohamed Ahmed

Answers:


101

“一切都是文件”有点麻烦。“一切都出现在文件系统中的某处”更接近商标,即使那样,它也比系统设计定律更理想。

例如,Unix域套接字不是文件,但是确实出现在文件系统中。您可以ls -l使用域套接字来显示其属性,与之之间的cat数据,通过chmod等修改其访问控制。

但是,即使使用与Unix域套接字相同的BSD套接字系统调用来创建和操纵常规的TCP / IP网络套接字,TCP / IP套接字也不会出现在文件系统中,¹尽管没有特别好的理由,是真实的。

在文件系统中出现的非文件对象的另一个示例是Linux的/proc文件系统。此功能向用户空间公开了有关内核运行时操作的大量详细信息,其中大部分是虚拟纯文本文件。许多/proc条目是只读的,但是许多条目/proc也是可写的,因此您可以使用任何可以修改文件的程序来更改系统的运行方式。las,这又是一个不理想的情况:BSD类型的Unix 通常在不使用的情况下运行/proc,并且System V Unix的暴露程度/proc比Linux 少得多。

我无法与MS Windows形成对比

首先,您可以在网上找到很多关于Unix成为文件I / O,而Windows在这方面“被破坏”的观点。Windows NT解决了很多问题。

Windows的现代版本与Unix一样,具有统一的I / O系统,因此您可以通过TCP / IP套接字ReadFile()而不是Windows套接字专用API 读取网络数据WSARecv()。这与Unix Way完全相同,在Unix Way中,您可以使用通用read(2)Unix系统调用或特定于套接字的调用从网络套接字读取信息recv(2)。²

但是,即使在2018年,Windows仍然无法将这一概念带入与Unix相同的水平。Windows体系结构的许多区域无法通过文件系统访问,或者不能视为类似于文件的区域。一些例子:

  1. 司机。

    Windows的驱动程序子系统很容易像Unix一样丰富和强大,但是要编写程序来操作驱动程序,通常必须使用Windows Driver Kit,这意味着编写C或.NET代码。

    在Unix类型的OS上,您可以从命令行对驱动程序做很多事情。如果仅通过将不需要的输出重定向到/dev/null.³ ,您几乎可以肯定已经做到了。

  2. 程序间通讯。

    Windows程序彼此之间不容易通信。

    Unix命令行程序可通过文本流和管道轻松进行通信。GUI程序通常是建立在命令行程序之上或导出文本命令界面,因此相同的基于文本的简单通信机制也可以与GUI程序一起使用。

  3. 注册表。

    Unix没有Windows注册表的直接等效项。同样的信息通过文件系统分散,在大多数的它/etc/proc/sys

如果看不到驱动程序,管道和Unix对Windows注册表的回答,则与“一切都是文件”有关,请继续阅读。

“一切都是文件”的哲学在这里有何不同?

我将在上面详细介绍我的三点来解释这一点。

长答案,第1部分:驱动器与设备文件

假设您的CF卡读卡器E:在Windows和/dev/sdcLinux 下都显示为。它有什么实际区别?

这不仅仅是语法上的微小差异。

在Linux上,我可以说用零dd if=/dev/zero of=/dev/sdc覆盖内容/dev/sdc

想一想那意味着什么。在这里,我有一个普通的用户空间程序(dd(1)),该程序要求从虚拟设备(/dev/zero)读取数据,然后/dev/sdc通过统一的Unix文件系统将其读出的内容写入实际的物理设备()。dd不知道它正在读写特殊设备。它将在普通文件上或在设备和文件的混合上工作,如下所示。

E:在Windows上没有简单的方法可以将驱动器归零,因为Windows区分文件和驱动器,因此您不能使用相同的命令来操作它们。最接近的方法是不使用“快速格式化”选项执行磁盘格式化,该选项会将大多数驱动器内容清零,然后在其上面写入一个新的文件系统。如果我不想要新的文件系统怎么办?如果我确实确实希望磁盘不填零,那该怎么办?

慷慨地说,我们确实确实希望在上拥有一个新的文件系统E:。要在Windows上的程序中执行此操作,我必须调用特殊的格式化API。⁴在Linux上,您无需编写程序即可访问操作系统的“格式化磁盘”功能。你只要运行相应的用户空间程序要创建的文件系统类型:mkfs.ext4mkfs.xfs,或者你有什么。这些程序会将文件系统写到/dev您传递的任何文件或节点上。

因为mkfsUnixy系统上的类型程序可以处理文件,而无需在设备和普通文件之间进行人为区分,所以这意味着我可以在Linux机器上的普通文件内创建ext4文件系统

$ dd if=/dev/zero of=myfs bs=1k count=1k
$ mkfs.ext4 -F myfs

这实际上在当前目录中创建了一个1 MiB磁盘映像,称为myfs。然后,可以像挂载其他任何外部文件系统一样挂载它:

$ mkdir mountpoint
$ sudo mount -o loop myfs mountpoint
$ grep $USER /etc/passwd > mountpoint/my-passwd-entry
$ sudo umount mountpoint

现在,我有了一个ext4磁盘映像,其中有一个名为的文件my-passwd-entry,其中包含用户的/etc/passwd条目。

如果需要,可以将该图像放大到CF卡上:

$ sudo dd if=myfs of=/dev/sdc1

或者,我可以打包该磁盘映像,将其邮寄给您,然后让您将其写入选择的介质中,例如USB记忆棒:

$ gzip myfs
$ echo "Here's the disk image I promised to send you." | 
  mutt -a myfs.gz -s "Password file disk image" you@example.com

在Linux⁵上所有这些都是可能的,因为文件,文件系统和设备之间没有人为的区别。Unix系统上的许多东西要么文件,要么是通过文件系统访问的,因此它们看起来像文件,或者以某种其他方式看起来像文件一样足以被视为文件。

Windows的文件系统概念是一个大杂烩。它区分目录,驱动器和网络资源。共有三种不同的语法,它们在Windows中都融合在一起:类Unix ..\FOO\BAR路径系统,驱动器字母(如C:)和UNC路径(如)\\SERVER\PATH\FILE.TXT。这是因为它是来自Unix,CP / MMS-DOSLAN Manager的思想的积累,而不是单一的一致设计。这就是Windows文件名中包含如此多非法字符的原因。

Unix具有统一的文件系统,所有内容均可通过单个通用方案访问。要在Linux机器上运行的程序,有没有功能差异/etc/passwd/media/CF_CARD/etc/passwd以及/mnt/server/etc/passwd。本地文件,外部媒体和网络共享都以相同的方式处理。

Windows可以达到与上面的磁盘映像示例类似的目的,但是您必须使用由非凡才华的程序员编写的特殊程序。这就是Windows上这么多“虚拟DVD”类型程序的原因。缺少核心操作系统功能已经为填补空白的程序创造了人为的市场,这意味着您需要一群人竞争来创建最佳的虚拟DVD型程序。我们在* ix系统上不需要此类程序,因为我们可以使用循环设备挂载ISO磁盘映像。

其他工具(例如磁盘擦除程序)也是如此,我们在Unix系统上也不需要这些工具。希望您的CF卡中的内容无法被扰乱而不是被置零吗?好的,将其/dev/random用作数据源,而不是/dev/zero

$ sudo dd if=/dev/random of=/dev/sdc

在Linux上,由于核心OS功能不仅运行良好,而且运行良好以至于被广泛使用,因此我们不会再发明这种轮子。引导Linux机器的一种典型方案涉及一个虚拟磁盘映像,仅举一个例子,该映像是使用上面显示的技术创建的。⁷

我觉得很公平地指出,如果Unix从一开始就将TCP / IP I / O集成到文件系统中,我们就不会有netcatvs socatvs Ncatvs mess,其原因与导致Windows上的磁盘映像和擦除工具激增:缺乏可接受的操作系统功能。nc

长答案,第2部分:管道作为虚拟文件

尽管Windows起源于DOS,但从来没有丰富的命令行传统。

这并不是说,Windows不会一个命令行,或者说,它缺少很多命令行程序。如今,Windows甚至具有非常强大的命令外壳,适当地称为PowerShell

但是,缺少命令行传统会产生连锁反应。您将获得DISKPARTWindows世界中几乎不为人知的工具,因为大多数人都通过计算机管理MMC管理单元来进行磁盘分区。然后,当您确实需要编写创建分区脚本的脚本时,您会发现DISKPART实际上并不是由其他程序来驱动的。是的,您可以将一系列命令写入脚本文件,然后通过来运行它DISKPART /S scriptfile,但这不是全部。在这种情况下,您真正想要的是更像GNU的parted东西,它将接受像这样的单个命令parted /dev/sdb mklabel gpt。这使您的脚本可以逐步进行错误处理。

这一切与“一切都是文件”有什么关系?容易:管道使命令行程序I / O成为一种“文件”。管道是单向,而不是像常规磁盘文件一样的随机访问,但是在许多情况下,差异并不重要。重要的是,您可以附加两个独立开发的程序,并使它们通过简单的文本进行通信。从这个意义上讲,考虑到Unix方式设计的任何两个程序都可以通信。

在确实需要文件的情况下,很容易将程序输出转换为文件:

$ some-program --some --args > myfile
$ vi myfile

但是,如果“一切都是文件”的理念为您提供了更好的方法,为什么还要将输出写入临时文件?如果您要做的只是将该命令的输出读入vi编辑器缓冲区,则vi可以直接为您执行此操作。在vi“正常”模式下,说:

:r !some-program --some --args

这会将程序的输出插入到当前光标位置的活动编辑器缓冲区中。在后台,vi使用管道将程序的输出连接到一些代码,这些代码使用与从文件读取相同的OS调用。如果的两种情况(:r即带和不带)!在的所有常见实现中都使用相同的通用数据读取循环,我不会感到惊讶vi。我想不出一个很好的理由。

这也不是的最新功能vi;可以追溯到古代的ed(1)文字编辑器。⁸

这个强大的主意一遍又一遍地出现在Unix中。

对于第二个示例,请回忆mutt上面的我的电子邮件命令。我必须将其编写为两个单独的命令的唯一原因是,我希望将临时文件命名为*.gz,以便可以正确命名电子邮件附件。如果我不在乎文件名,则可以使用进程替换来避免创建临时文件:

$ echo "Here's the disk image I promised to send you." | 
  mutt -a <(gzip -c myfs) -s "Password file disk image" you@example.com

通过将输出gzip -c转换为FIFO(类似于文件)或/dev/fd对象(类似于文件),可以避免临时情况。(Bash根据系统的功能选择方法,因为/dev/fd并非到处都有。)

对于这种强大想法在Unix中出现的第三种方式,请考虑gdb在Linux系统上。这是用于用C和C ++编写的任何软件的调试器。从其他系统进入Unix的程序员看着gdb并且几乎总是对它感到困惑,“哎呀,它是如此原始!” 然后他们去寻找一个GUI调试器,找到存在的调试器中的一个,然后高兴地继续他们的工作……通常从来没有意识到GUI只是在gdb下面运行,并在其上面提供了一个漂亮的外壳。在大多数Unix系统上,没有竞争的低级调试器,因为不需要程序在该级别上竞争。我们需要的是一个很好的低级工具,只要该低级工具可以通过管道轻松通信,我们就可以以此为基础。

这意味着我们现在有一个文档化的调试器接口,该接口可以直接替换gdb,但不幸的是,主要竞争对手gdb 没有采用低摩擦的方法

尽管如此,至少将来有可能gdb会简单地通过克隆其命令行界面来透明地插入某些将来的替换。为了在Windows机器上实现同样的目标,可替换工具的创建者必须定义某种形式的正式插件或自动化API。这意味着除了最流行的程序之外,它不会发生,因为要构建普通的命令行用户界面和完整的编程API会花费很多工作。

通过基于文本的无处不在的IPC的魅力,这种魔力得以实现。

尽管Windows的内核具有Unix风格的匿名管道,但是很少看到普通用户程序在命令外壳之外将它们用于IPC,因为Windows缺乏这种传统,即首先在命令行版本中创建所有核心服务,然后在其上构建GUI。它的顶部。这导致没有GUI无法做某些事情,这就是为什么与Linux相比Windows 拥有如此多的远程桌面系统的原因之一:没有GUI很难使用Windows。

相比之下,通常通过SSH远程管理Unix,BSD,OS X和Linux机器。您问这是如何工作的?SSH连接网络套接字(它是文件等)到一个伪TTY/dev/pty*(这是与文件等)。现在,您的远程系统通过与Unix方式无缝匹配的连接连接到本地系统,从而可以根据需要通过SSH连接传输数据

您是否知道这个概念现在有多强大?

从程序的角度来看,管道式文本流与文件是无法区分的,只是它是单向的。程序从管道读取文件的方式与从文件读取管道的方式相同:通过文件描述符。FD绝对是Unix的核心。文件和管道对I / O使用相同的抽象这一事实应该告诉您一些东西。

Windows世界缺乏这种简单的文本通信的传统,而是通过COM.NET来处理重量级的OOP接口。如果需要使这样的程序自动化,则还必须编写一个COM或.NET程序。这比在Unix机器上设置管道要困难得多。

缺少这些复杂的编程API的Windows程序只能通过较差的界面(例如剪贴板或文件/保存,然后是文件/打开)进行通信。

长答案,第3部分:注册表与配置文件

Windows注册表和Unix系统配置方式之间的实际区别也说明了“一切都是文件”理念的好处。

在Unix类型的系统上,我仅通过检查文件就可以从命令行查看系统配置信息。我可以通过修改那些相同的文件来更改系统行为。在大多数情况下,这些配置文件只是纯文本文件,这意味着我可以使用Unix上的任何工具来操作它们,以使用纯文本文件。

在Windows上编写注册表脚本并不是那么容易。

最简单的方法是在一台计算机上通过注册表编辑器GUI进行更改regedit*.reg,然后通过via 文件将这些更改盲目地应用于其他计算机。那并不是真正的“脚本”,因为它不允许您有条件地做任何事情:全部或全部。

如果您的注册表更改需要任何数量的逻辑,则下一个最简单的选择是学习PowerShell,这基本上就相当于学习.NET系统编程。就像Unix仅具有Perl,而您必须通过它进行所有临时系统管理一样。现在,我是Perl的粉丝,但并不是每个人都如此。Unix允许您使用碰巧喜欢的任何工具,只要它可以操纵纯文本文件即可。


脚注:

  1. 计划9固定这个设计失误,经由暴露网络I / O /net虚拟文件系统

    Bash具有一项称为的功能/dev/tcp该功能允许通过常规文件系统功能进行网络I / O。由于它是Bash功能,而是内核功能,因此在Bash外部或根本不使用Bash的系统上不可见。通过反例显示了为什么通过文件系统显示所有数据资源是一个好主意。

  2. 我所说的“现代Windows”是指Windows NT及其所有直接后代,包括Windows 2000,Windows Server的所有版本以及从XP开始的所有面向桌面的Windows版本。我用这个术语来排除Windows的基于DOS的版本,即Windows 95及其直接后代,Windows 98和Windows ME以及它们的16位前身。

    您可以看到这些区别是由于后者的OS中缺少统一的I / O系统。您不能将TCP / IP套接字传递ReadFile()到Windows 95上。您只能将套接字传递给Windows套接字API。请参阅安德鲁·舒尔曼(Andrew Schulman)的开创性文章《Windows 95:不是什么》,以更深入地探讨该主题。

  3. 毫无疑问,它/dev/null是Unix类型系统上的真正内核设备,而不仅仅是NULWindows中表面上等效的特殊大小写文件名。

    尽管Windows试图阻止您创建NUL文件,但是可以通过欺骗Windows的文件名解析逻辑而仅通过欺骗来绕过此保护。如果您尝试使用cmd.exe或Explorer 访问该文件,则Windows将拒绝打开该文件,但您可以通过Cygwin对其进行写入,因为它使用与示例程序类似的方法来打开文件,并且可以通过类似的技巧将其删除。

    相比之下,rm /dev/null只要您具有对的写访问权,Unix就会很乐意让您,/dev并允许您在原处重新创建一个新文件,而这一切都不花钱,因为该dev节点只是另一个文件。当缺少那个dev节点时,内核的空设备仍然存在;只有通过来重新创建dev节点之前,它才不可访问mknod

    您甚至可以在其他位置创建其他null设备dev节点:调用它并不重要/home/grandma/Recycle Bin,只要它是null设备的dev节点,它将与完全相同/dev/null

  4. Windows 中实际上有两个高级“格式磁盘” API:SHFormatDrive()Win32_Volume.Format()

    Windows非常有两个原因。第一个要求Windows资源管理器显示其正常的“格式化磁盘”对话框,这意味着它可以在任何现代版本的Windows上运行,但只能在用户以交互方式登录时使用。另一个可以在没有用户输入的情况下在后台调用,但是直到Windows Server 2003才将它添加到Windows中。是的,直到2003年,在Unix mkfs 从第一天开始出货的世界中,核心操作系统的行为就一直隐藏在GUI后面。

    我从1974年开始的Unix V5副本包括/etc/mkfs一个4136字节静态链接的PDP-11可执行文件。(Unix 直到1980年代后期才获得动态链接,因此,好像其他地方没有大型图书馆可以完成所有实际工作。)其源代码(包括在V5系统映像中/usr/source/s2/mkfs.c)是完全独立的457- C行程序。甚至没有任何#include声明!

    这意味着您不仅可以mkfs从高层次检查什么,还可以使用创建Unix的相同工具集进行试验,就像您是四十年前的Ken Thompson一样。在Windows上尝试一下。今天,您可以找到的最接近的是下载2014年首次发布的DOS源代码,您发现它只是一堆汇编源代码。它只会使用您可能没有的过时的工具进行构建,最终您将获得自己的DOS 2.0副本,尽管它在将近十年后发布,但它的功能远不如1974年的Unix V5强大。

    (为什么要谈论Unix V5?因为它仍然是最早可用的完整Unix系统。早期版本显然已被淘汰。有一个项目将V1 / V2时代的Unix拼凑在一起,但mkfs尽管存在,但似乎仍在丢失上面链接的V1手册页中的某个部分证明它一定存在于某个地方,或者是那些将这个项目放在一起的人找不到包含的现存副本mkfs,或者我很想找到没有的文件find(1),而该文件在该系统中也不存在。:)

    现在,您可能会想:“我不能只打电话format.com吗?Windows上的电话mkfs与Unix 上的电话不一样吗?” las,不,原因不尽相同,原因有很多:

    • 首先,format.com并非旨在编写脚本。它提示您“准备好后按ENTER”,这意味着您需要向其输入发送Enter键,否则它将挂起。

    • 然后,如果您想要获得成功/失败状态代码以外的其他信息,则必须打开其标准输出以进行读取,这在Windows上比必须的要复杂得多。(在Unix上,该链接文章中的所有内容都可以通过一个简单的popen(3)调用来完成。)

    • 经历了所有这些复杂的过程之后,format.com对于计算机程序而言,的输出要比mkfs主要用于人类消费的的输出更难解析。

    • 如果您跟踪什么format.com呢,你会发现它做了一堆复杂的呼叫来DeviceIoControl()ufat.dll和这样的。这不仅仅是打开设备文件并将新文件系统写入该设备。这是您从拥有126000名员工的公司获得的设计,并且需要继续雇用他们。

  5. 在谈论循环设备时,我通常只谈论Linux而不是Unix,因为循环设备不能在Unix类型的系统之间移植。OS X,BSD等中也有类似的机制,但是语法有所不同

  6. 在磁盘驱动器只有洗衣机大小且成本比部门负责人的豪华轿车贵的时代,与现代计算环境相比,大型计算机实验室将共享其集体磁盘空间更大的比例。将远程磁盘透明地移植到本地文件系统中的能力使这种分布式系统更易于使用。例如,这就是我们得到的地方/usr/share

    对比Windows,通常将远程磁盘映射到驱动器号或必须通过UNC路径进行访问,而不是透明地集成到本地文件系统中。驱动器符为您提供很少的符号表达选择;是P:指BigServer上的“公共”空间,还是软件镜像服务器上的“ packages”目录?UNC路径意味着您必须记住远程文件所在的服务器,而在拥有成百上千个文件服务器的大型组织中,这变得很困难。

    直到2007年发布的Windows Vista引入了NTFS符号链接,Windows才获得符号链接。Windows的符号链接比Unix的符号链接(自1977年以来一直是Unix的功能)要强大一些,因为它们还可以指向远程文件共享,而不仅仅是指向本地路径。Unix 在1984年通过NFS进行了不同的操作,它基于Unix 自一开始就已具有的挂载点功能。

    因此,根据您的看法,Windows落后Unix大约2到3年。

    即使这样,出于几个原因,符号链接也不是Windows用户体验的正常部分。

    首先,您只能使用向后命令行程序来创建它们MKLINK。您无法从Windows资源管理器创建它们,而UNIX的等价Windows资源管理器一般让你创建符号链接。

    其次,默认的Windows配置阻止普通用户创建符号链接,这要求您要么以管理员身份运行命令外壳,要么授予用户通过普通用户从未见过的工具中晦涩的路径创建它们的权限,而很少有人知道如何使用。(并且与Windows中的大多数管理员权限问题不同,在这种情况下,UAC没有帮助。)

  7. Linux机器在引导顺序中并不总是使用虚拟磁盘映像。有很多不同的方法可以做到这一点

  8. man ed

  9. 顺便说一下,网络套接字描述符也位于其下。


7
有趣的是,cygwin通过/proc/registryMS Windows上的伪文件系统使Windows注册表可用(尽管目前为只读)。
斯特凡Chazelas

-3

如果您认为Linux作为英语语言,则file systems字母,其基本上是为基础块英语

在文件系统的Wiki页面中,

在计算中,文件系统(或文件系统)用于控制数据的存储和检索方式。如果没有文件系统,放置在存储区域中的信息将是一个庞大的数据主体,无法分辨一条信息在哪里停止,而另一条信息在哪里开始。

因此,如果外行人没有适当的英语语言结构(由字母组成),人与人之间的互动将不会产生任何意义。同样,没有文件系统,底层存储设备中拥有的任何数据将没有真正的意义。


不是那么抽象,这个答案简而言之。
Mohamed Ahmed 2014年

@MohamedAhmed,请参阅。
拉梅什(Ramesh)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.