我最近阅读了命名管道,但我不明白它们为什么存在。
我在某处读到使用命名管道比使用文件更省时。
为什么会这样?
命名管道也必须存储在内存中(可能会被交换,就像文件一样)。
据我所知,他们必须获得一个必须由当前目录引用的 inode,就像文件一样。此外,它们必须由程序员删除,就像文件一样。
那么优势在哪里呢?
c0r*_*0rp 56
Linux 中的几乎所有东西都可以被视为文件,但常规文件和命名管道之间的主要区别在于,命名管道是文件系统上没有内容的文件的特殊实例。
这是引自man fifo:
FIFO 特殊文件(命名管道)类似于管道,不同之处在于它作为文件系统的一部分进行访问。它可以被多个进程打开以进行读取或写入。当进程通过 FIFO 交换数据时,内核在内部传递所有数据而不将其写入文件系统。因此,FIFO 特殊文件在文件系统上没有内容;文件系统条目仅用作参考点,以便进程可以使用文件系统中的名称访问管道。
内核为至少一个进程打开的每个 FIFO 特殊文件维护一个管道对象。FIFO 必须在两端(读和写)都打开,然后才能传递数据。通常,打开 FIFO 会阻塞,直到另一端也打开。
所以实际上一个命名管道在某些进程读写它之前什么都不做。它不占用硬盘上的任何空间(除了一点元信息),它不使用 CPU。
您可以通过执行以下操作来检查它:
创建命名管道
$ mkfifo /tmp/testpipe
Run Code Online (Sandbox Code Playgroud)
转到某个目录,例如/home/user/Documents,使用命名管道 gzip 里面的所有内容。
$ cd /home/user/Documents
$ tar cvf - . | gzip > /tmp/testpipe &
[1] 28584
Run Code Online (Sandbox Code Playgroud)
在这里您应该会看到 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
Run Code Online (Sandbox Code Playgroud)
您将看到它不使用任何资源。CPU 使用率 0%,内存使用率 0%。
验证有关文件空间使用情况的预感
$ du -h /tmp/testpipe
0 testpipe
Run Code Online (Sandbox Code Playgroud)
再一次0,什么都没有。如果需要,可以再次使用试管。
不要忘记使用kill -15 28584. 并使用删除我们的命名管道rm /tmp/testpipe
示例用法
您可以使用命名管道重定向几乎所有内容。例如,您可以看到这一行代理。
另外这里是一个更命名管道的使用很好的解释。您可以将一台服务器上的两个进程配置为使用命名管道而不是 TCP/IP 堆栈进行通信。它更快,并且不会加载网络资源。例如,您的 Web 服务器可以使用命名管道直接与数据库通信,而不是使用localhost地址或侦听某个端口。
GAR*_*vid 19
确实,您不会使用系统内存,但您在示例中不使用 cpu 的事实只是因为您没有读取管道,因此进程正在等待。
考虑以下示例:
mkfifo /tmp/testpipe
tar cvf - / | gzip > /tmp/testpipe
Run Code Online (Sandbox Code Playgroud)
现在打开一个新的控制台并运行:
watch -n 1 'ps u -P $(pidof tar)
Run Code Online (Sandbox Code Playgroud)
在第三个控制台中:
cat /tmp/testpipe > /dev/null
Run Code Online (Sandbox Code Playgroud)
如果您查看 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
Run Code Online (Sandbox Code Playgroud)
使用命名管道你会做
mkfifo BigFileSplitOrig_05
dd if=BigFile of=BigFileSplitOrig_05 bs=1G skip=4 count=1 &
diff -s BigFileSplitOrig_05 BigFileSplit_05
rm BigFileSplitOrig_05
Run Code Online (Sandbox Code Playgroud)
乍一看,这似乎没有太大区别……但随着时间的推移,差异是巨大的!
选项1:
选项 2:
所以基本上命名管道在这里为您节省了 1G 的读写以及一些文件系统清理(因为我们没有向文件系统写入任何内容,而是空的 fifo 节点)。
不进行 I/O,尤其是写入,也有助于避免磁盘磨损。使用 SSD 时更有趣,因为它们在单元死亡之前的写入次数有限。
(1) 显然,另一种选择是将临时文件创建到 RAM,例如,如果 /tmp 挂载到 RAM (tmpfs)。然而,您会受到 RAM 磁盘大小的限制,而“命名管道技巧”则没有限制。
| 归档时间: |
|
| 查看次数: |
81788 次 |
| 最近记录: |