为什么使用命名管道而不是文件?

我最近读到了有关命名管道的内容,我无法理解为什么它们存在。
我在某处读过使用命名管道比使用文件耗时少。

为什么会这样?
命名管道也必须存储在内存中(并且可能交换,就像文件一样)。
据我所知,他们必须获得一个必须由当前目录引用的inode,就像文件一样。 此外,它们必须由程序员删除,就像文件一样。

那么优势在哪里呢?

Linux中的几乎所有内容都可以被视为文件 ,但常规文件命名管道之间的主要区别在于命名管道是文件系统中没有内容的文件的特殊实例。

以下是man fifo引用:

FIFO特殊文件(命名管道)类似于管道,除了它作为文件系统的一部分进行访问。 它可以通过多个读取或写入过程打开。 当进程通过FIFO交换数据时,内核会在内部传递所有数据,而不会将其写入文件系统。 因此,FIFO特殊文件在文件系统上没有内容; 文件系统条目仅用作参考点,以便进程可以使用文件系统中的名称访问管道。

内核为至少一个进程打开的每个FIFO特殊文件保留一个管道对象。 在传递数据之前,必须在两端打开FIFO(读取和写入)。 通常,打开FIFO块直到另一端打开。

因此,实际上命名管道在某些进程读取和写入之前不会执行任何操作。 它不占用硬盘上的任何空间(除了一些元信息),它不使用CPU。

您可以通过执行以下操作进行检查:

创建命名管道

 $ mkfifo /tmp/testpipe 

转到某个目录,例如/home/user/Documents ,并使用命名管道gzip其中的所有内容。

 $ cd /home/user/Documents $ tar cvf - . | gzip > /tmp/testpipe & [1] 28584 

在这里你应该看到gzip进程的PID。 在我们的例子中它是28584。

现在检查这个PID正在做什么

 $ ps u -P 28584 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND c0rp 28584 0.0 0.0 29276 7800 pts/8 S 00:08 0:00 bash 

您将看到它没有使用任何资源 。 0%CPU使用率,0%内存使用率。

validation有关文件空间使用情况的预感

 $ du -h /tmp/testpipe 0 testpipe 

而且0 ,没有。 如果需要,可以再次使用测试管。

不要忘记杀死gzip,使用kill -15 28584 。 并使用rm /tmp/testpipe删除我们的命名管道

示例用法

您可以使用命名管道重定向几乎所有内容。 例如,您可以看到这一行代理 。

这里还有一个关于命名管道使用的更好的解释。 您可以在一台服务器上配置两个进程,以使用命名管道而不是TCP / IP堆栈进行通信。 它更快,并且不加载网络资源。 例如,您的Web服务器可以使用命名管道直接与数据库通信,而不是使用localhost地址或侦听某个端口。

确实,您不会使用系统内存,但在您的示例中不使用cpu这一事实仅仅是因为您没有读取管道,因此进程正在等待。

请考虑以下示例:

 mkfifo /tmp/testpipe tar cvf - / | gzip > /tmp/testpipe 

现在打开一个新的控制台并运行:

 watch -n 1 'ps u -P $(pidof tar) 

在第三个控制台:

 cat /tmp/testpipe > /dev/null 

如果你看一下手表cmd(第二学期)它会显示cpu消耗的增加!

这是一个用例,命名管道可以通过删除I / O为您节省大量时间。

假设您有一个BigFile,例如10G。

你还可以将这个BigFile拆分为1G,BigFileSplit_01到BigFile_Split_10。

现在你对BigFileSplit_05的正确性有疑问

天真地,没有命名管道,你将从BigFile创建一个新的拆分并比较:

 dd if=BigFile of=BigFileSplitOrig_05 bs=1G skip=4 count=1 diff -s BigFileSplitOrig_05 BigFileSplit_05 rm BigFileSplitOrig_05 

使用命名管道你会做

 mkfifo BigFileSplitOrig_05 dd if=BigFile of=BigFileSplitOrig_05 bs=1G skip=4 count=1 & diff -s BigFileSplitOrig_05 BigFileSplit_05 rm BigFileSplitOrig_05 

乍一看似乎没有什么大不同……但是时间差异很大!

选项1:

  • dd:读1G /写1G (1)
  • 差异:读取2G
  • rm:免费分配的群集/删除目录条目

选项2:

  • dd:什么都没有! (去命名管道)
  • 差异:读取2G
  • rm:没有分配的集群来管理(我们实际上没有写任何文件系统)/删除目录条目

所以基本上命名管道在这里节省了1G的读写以及一些文件系统清理(因为我们没有向文件系统写入任何内容但空的fifo节点)。

不做I / O,尤其是写入,也可以避免磁盘磨损。 使用SSD时更有趣,因为在单元格死亡之前它们的写入次数有限。

(1)显然,另一种选择是将该临时文件创建到RAM,例如,如果/ tmp安装到RAM(tmpfs)。 然而,你会受到RAM磁盘大小的限制,而“命名管道技巧”没有限制。

你可以让一个程序静止不动,并为一些外部事件监听命名管道。 一旦外部事件发生(f.ex.一些新数据到达),这可以由一些其他程序检测到,这些程序又打开管道进行写入,将相关事件数据写入管道。 当发出close语句时,监听程序将通过读取语句通过管道接收数据流,并准备好处理它所获得的内容。 阅读完内容后,请不要忘记关闭管道。 监听程序还可以通过相同的方式或通过另一个命名管道返回其处理结果。 这种节目间通信有时非常方便。