我们经常使用类似cmd0|命令1|cmd2在命令行中。其实这就是管道重定向(piperedirection),用于将一个命令的输出重定向为下一个命令的输入。那么,你真的知道它是如何工作的吗?今天让我们仔细看看。注意:本文将在多处使用术语Unix(而不是Linux),因为管道的概念起源于Unix。Linux中的管道:一般概念什么是Unix管道?Unix管道是一种IPC(进程间通信)机制,它将一个程序的输出转发到另一个程序的输入。现在,让我们用更专业易懂的语言重新解释一下:Unix管道是一种IPC(InterProcessCommunication,进程间通信)机制,它接收程序的标准输出(stdout),并通过缓冲区转发给另一个程序的标准输入(stdin)。这个描述大家应该都能看懂。请参阅下图以了解管道的工作原理:管道命令最简单的示例之一是将一些命令输出通过管道传输到grep命令以搜索特定字符串。例如,我们可以搜索名称中包含txt的文件,如下:pipe将标准输出重定向到标准输入,但不作为命令参数。非常重要的是要注意管道命令将标准输出(stdout)传递给另一个A命令的标准输入(stdin),但不是作为参数。下面我们举一个例子来说明这一点。如果我们使用不带任何参数的cat命令,它将默认从标准输入读取。请参见以下示例:$catHello,myfriend.^DHello,myfriend。在上面的示例中,cat没有任何参数地使用,因此默认情况下它将读取stdin。接下来,我写了一行文本并按Ctrl+d告诉它我完成了(Ctrl+d表示EOF或文件结尾)。然后,cat命令读取stdin,然后将我之前写的行输出到终端。现在,看看命令:echohey|cat管道右边的命令不等于cat嘿。在这里,标准输出(stdout)“hey”被缓冲并通过管道传输到cat命令的标准输入(stdin)。由于没有命令行参数,默认情况下cat会读取stdin,而stdin恰好包含某些内容(即“嘿”),因此cat会读取它并将其打印到stdout。为了演示差异,我们可以创建一个名为hey的文件并向其中添加一些文本。见下图:Linux中的管道类型Linux中的管道有两种类型:1)匿名管道,即无名管道;2)命名管道。匿名管道顾名思义,匿名管道没有名字。当您使用|时,它们由Unixshell动态创建。象征。我们通常所说的管道是指匿名管道。它使用起来非常方便,而且作为最终用户,我们不需要跟踪它的操作,shell会自动处理这一切。命名管道这一点略有不同,文件系统中确实存在命名管道。它们像普通文件一样存在,可以使用以下命令创建命名管道:mkfifopipe这将创建一个名为管道的文件,执行以下命令:$ls-lpipeprw-r--r--。1gliugliu0Aug417:23pipe注意开头的“p”,表示该文件是一个管道。现在让我们使用这个管道。如前所述,管道将一个命令的输出转发到另一个命令的输入。这就像快递服务,您可以将包裹从一个地址运送到另一个地址。所以第一步是交付包裹。echohey>pipe我们会看到没有打印回显信息,看起来像是挂了。新开一个终端,尝试读取文件:catpipe我们看看两个终端的输出,如下图所示:惊讶吗?两个命令同时完成执行。这是普通文件和命名管道的基本区别之一。在另一个进程读取管道之前,不会向管道写入任何内容。那么,为什么要使用命名管道呢?让我们来看看。命名管道不占用磁盘上的任何内存。如果我们执行命令du-spipe,我们会看到它不占用任何空间。这是因为命名管道就像从内存缓冲区读取和写入的端点。写入命名管道的任何内容实际上都存储在一个临时内存缓冲区中,当从另一个进程执行读取时,该缓冲区会被刷新。节省IO,因为写入命名管道意味着将数据存储到内存缓冲区中,因此如果涉及涉及大文件的操作,则会大大减少磁盘I/O。两个不同进程之间的通信使用命名管道有效地实时获取另一个进程的事件输出。因为读取和写入同时发生,所以没有延迟。底层管道理解(针对高级用户和开发人员)接下来我们更深入地讨论管道,以及具体的实现。这些需要对以下内容有基本的了解:C程序如何工作;什么是系统调用;什么是流程;什么是文件描述符。我们不会详细介绍这些概念,只讨论管道相关的内容。对于大多数Linux用户,可以选择性阅读以下内容。为了进行编译,本文末尾提供了一个示例makefile。当然,这只是用于说明的伪代码。请参见以下程序://pipe.c#include
