程序如何知道要在管道中读取什么?

程序如何知道要在管道中读取什么?

unix 命令行程序如何知道要读取哪个文件?

例如:

 cat someFile | foo

程序如何foo知道要读取哪个文件,以及哪个进程负责从磁盘打开和读取该文件?

答案1

foo不知道要读取什么文件,它(大概)只是从其标准输入流中读取。该数据流由 shell 连接到命令的标准输出流cat。这种“管理管道”是由 shell 在启动两个进程(它们将同时运行)时完成的。

在问题的示例中,它将cat打开文件进行读取,读取文件并将数据传递到其标准输出。

你不妨问“怎么cat知道把结果写到哪里呢?”答案是它写入其标准输出流,通过 shell 连接到命令的标准输入流foo。同样,该命令的标准输出流foo通过 shell 连接到终端,因为该命令没有进一步的管道或重定向。


您展示的管道,

cat someFile | foo

功能上与

foo <somefile

这里我已经删除了,cat因为它不是真正需要的。 shell 会将 的标准输入流连接到foo给定的文件,因此效果是相同的(foo能够somefile从其标准输入流读取 的内容)。

在最后一个命令中,foo仍然不知道它读取来自名为 的文件的数据somefile。它也不知道它不再从 的输出中读取cat。它只是像以前一样读取其标准输入流。

现在是 shell 打开文件somefile进行读取,但 shell 不会从文件中读取任何内容,只是将标准输入流与打开的文件挂钩以进行foo读取。


请注意,我们不知道该foo命令的作用是什么,也不知道它是否真的起作用任何事物使用其标准输入流,或者是否期望从其命令行读取文件名。此类信息可在程序手册中找到foo

foo在实际情况下需要要被告知通过在命令行上给定路径名来读取特定文件,您可以使用

foo somefile

现在foo将负责打开和读取文件。

如果必须以某种方式处理文件(假设“ cat”是一个更复杂的过程,实际上会修改从 读取的数据somefile):

cat somefile >newfile
foo newfile
rm newfile

即,处理文件并将结果保存在新的临时文件中,然后将临时文件的名称传递给foo.然后删除临时文件。

或者,使用能够理解进程替换的 shell(例如bash):

foo <( cat somefile )

在这里,shell 会安排将 的输出cat somefile写入临时文件(或命名管道,这并不重要),并且该数据的路径名将被插入以代替进程替换<( ... )foo然后将其打开作为要读取的文件。

在最后一个示例中,cat将打开原始文件并从中读取,同时foo将打开 shell 提供的任何路径名(找到 的输出cat)并从中读取。

答案2

其中cat someFile | foo包含三个要素:

  1. cat someFile
  2. 管道|
  3. foo

现在发生了什么事:

  1. cat知道它应该读作someFile,因为这就是它的名字,所以销售告诉它细节。也就是说,someFile这里是一个参数,所有参数都会传递给被调用的应用程序。

  2. 管道使 shell 分叉子 shell 并在其中启动进程,以及排列子 shell 和进程,尤其是设置它们的输入和输出。这就是foo从 获取输入的方式cat

  3. foo叫法和cat以前一样。但在第二步之后(实际上是 shell 中的第一步),输入foo来自cat.这就是管道的名称。

答案3

您编写了两个命令:cat someFilefoo。第一个命令必须读取someFile并写入它,standard output并将其重定向到pipe.下一个命令从其读取数据,standard input该数据被重定向到 的输出pipe

标准输入、标准输出和标准错误输出是基本的 Linux 术语,重定向和管道是程序之间数据流动的最强大原理。请查找这些术语来了解 Linux 命令行的基础知识。

相关内容