问题描述
我最近读到了有关命名管道的内容,我无法理解为什么它们存在。我在某处读过使用命名管道比使用文件更少time-consuming。
为什么会这样?命名管道也必须存储在内存中(并且可能交换,就像文件一样)。据我所知,他们必须获得一个必须由当前目录引用的inode,就像文件一样。此外,它们必须由程序员删除,就像文件一样。
那么优势在哪里呢?
最佳解决方法
Linux中的几乎所有内容都可以被视为文件,但常规文件和命名管道之间的主要区别在于命名管道是文件系统中没有内容的文件的特殊实例。
以下是man fifo
的引用:
A FIFO special file (a named pipe) is similar to a pipe, except that it is accessed as part of the filesystem. It can be opened by multiple processes for reading or writing. When processes are exchanging data via the FIFO, the kernel passes all data internally without writing it to the filesystem. Thus, the FIFO special file has no contents on the filesystem; the filesystem entry merely serves as a reference point so that processes can access the pipe using a name in the filesystem.
The kernel maintains exactly one pipe object for each FIFO special file that is opened by at least one process. The FIFO must be opened on both ends (reading and writing) before data can be passed. Normally, opening the FIFO blocks until the other end is opened also.
实际上,命名管道在某些进程读取和写入之前不会执行任何操作。它不占用硬盘上的任何空间(除了一些元信息),它不使用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%内存使用率。
验证有关文件空间使用情况的预感
$ du -h /tmp/testpipe
0 testpipe
又一次0
,没什么。如果需要,可以再次使用测试管。
不要忘记使用kill -15 28584
杀死gzip。并使用rm /tmp/testpipe
删除我们的命名管道
示例用法
您可以使用命名管道重定向几乎所有内容。例如,您可以看到此one line proxy。
还有here is one more对命名管道使用情况的很好解释。您可以在一台服务器上配置两个进程,以使用命名管道而不是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
如果你看一下 watch 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磁盘大小的限制,而“命名管道技巧”没有限制。