我听说 FIFO 是命名管道。它们具有完全相同的语义。另一方面,我认为 Unix 域套接字与管道非常相似(尽管我从未使用过它)。所以我想知道它们是否都指的是 Linux 内核中的相同实现。任何的想法?
我使用该mkfifo <file>
命令创建了命名的 FIFO,其中一个进程写入文件,另一个进程从文件中读取。
现在,我知道该mknod
命令能够创建命名管道。这些命名管道是否等同于由创建的 FIFO mkfifo
,或者它们具有不同的功能?
我已配置rsyslog
将某些日志事件记录到/dev/xconsole
:
*.*;cron.!=info;mail.!=info |/dev/xconsole
Run Code Online (Sandbox Code Playgroud)
/dev/xconsole
是一个命名管道 ( fifo
)。如果我想查看正在记录的内容,我可以做cat /dev/xconsole
. 我很惊讶地看到,该命令cat /dev/xconsole
在读取文件后并未完成,而是充当tail -f
. 换句话说,这两个命令的行为相同:
cat /dev/xconsole
tail -f /dev/xconsole
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下这是为什么吗?
两者之间有什么区别吗?
我试图了解命名管道的工作原理,以便我可以简化我的单向进程间通信。由于将数据复制到循环缓冲区中,我预计会产生一些开销,我原以为它存储在 RAM 中,因此我预计管道比写入文件快得多(因为 RAM 比磁盘快几个数量级)。
相反,我发现命名管道(或匿名管道)与文件的速度大致相同。这是在带有普通磁盘驱动器(非固态)、运行 Ubuntu Linux 的 3 GHz 桌面上。这是一个简化的 Python 测试程序:
import sys
import time
import random
megabyte = "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for x in range(1024**2))
while True:
before = time.time()
sys.stdout.write(megabyte)
after = time.time()
sys.stderr.write("{} microseconds\n".format(1e6 * (after - before)))
Run Code Online (Sandbox Code Playgroud)
管道直通/dev/null
:
python test.py > /dev/null
Run Code Online (Sandbox Code Playgroud)
每兆字节产生 2.1 微秒(常数)。
管道到文件:
python test.py > /tmp/testout.txt
Run Code Online (Sandbox Code Playgroud)
在 500 微秒和 930 微秒之间跳跃(随着文件变大,更大的值变得更常见——据推测,它正在寻找磁盘空间)。
然后命名管道:
mkfifo testpipe
cat testpipe > /dev/null &
python test.py > testpipe
Run Code Online (Sandbox Code Playgroud)
产生 640 微秒(常数)和一个未命名的管道:
python test.py | …
Run Code Online (Sandbox Code Playgroud) 我有一个程序在读取给定流中的 EOF 时自动退出(在以下情况下为 stdin )。
现在我想制作一个 shell 脚本,它创建一个命名管道并将程序的 stdin 连接到它。然后脚本使用and (以及其他在退出时自动生成 EOF 的工具)多次写入管道。我面临的问题是,当第一个完成时,它会向管道发送一个 EOF 并使程序退出。如果我使用类似的东西,那么当我打算退出程序时,我将无法发送 EOF。我正在研究一个平衡的解决方案,但无济于事。
我已经找到了如何防止 EOF 以及如何手动发送 EOF,但我无法将它们结合起来。有什么提示吗? echo
cat
echo
tail -f
#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg
Run Code Online (Sandbox Code Playgroud) 有没有办法创建一个类似于这样的文件系统对象:
mknod files p
cat file1 file2 ... fileN > files
Run Code Online (Sandbox Code Playgroud)
但是这样就可以找到它,就好像它是一个普通文件一样?
如果myfile
随着时间的推移而增加,我可以使用每秒获得行数
tail -f | pv -lr > /dev/null
Run Code Online (Sandbox Code Playgroud)
它提供瞬时速度,而不是平均速度。
我怎样才能得到平均速度(即速度函数v(t)
在监控时间内的积分)。
我有一个输入文件,其中包含一些用开始和结束标记划分的部分,例如:
line A
line B
@@inline-code-start
line X
line Y
line Z
@@inline-code-end
line C
line D
Run Code Online (Sandbox Code Playgroud)
我想对这个文件应用一个转换,使得 X、Y、Z 行通过一些命令(nl
例如)过滤,但其余的行不变地通过。请注意,nl
(数字线)跨行累积状态,因此它不是应用于每条线 X、Y、Z 的静态转换。(编辑:有人指出nl
可以在不需要累积状态的模式下工作,但我只是nl
作为一个例子来简化问题。实际上,该命令是一个更复杂的自定义脚本。我真正在寻找的是for 是将标准过滤器应用于输入文件的一部分的问题的通用解决方案)
输出应如下所示:
line A
line B
1 line X
2 line Y
3 line Z
line C
line D
Run Code Online (Sandbox Code Playgroud)
文件中可能有几个这样的部分需要转换。
更新 2我最初没有指定如果有更多部分会发生什么,例如:
line A
line B
@@inline-code-start
line X
line Y
line Z
@@inline-code-end
line C
line D
@@inline-code-start
line L
line M
line N …
Run Code Online (Sandbox Code Playgroud) 谢谢sshfs
魔术,我可以从远程服务器挂载我的主目录
sshfs user@server:/home/user ~/remote
Run Code Online (Sandbox Code Playgroud)
乐观地,我认为我会在(在挂载中)设置一个本地inotify
-hook,以便本地程序可以对远程日志更改做出反应。~/remote/logFile
sshfs
cd ~/remote
touch logFile # create remote file
inotifywait logFile & # set up local inotify-hook
ssh user@server -x touch /home/user/logFile # touch file from remote
Run Code Online (Sandbox Code Playgroud)
什么也没有发生。inotifywait
除非我touch
在本地保存文件,否则是无声的。写入命名管道同样失败。
为什么是这样?
我怎样才能弥合这个差距?
我可以inotifywait
在远程运行,修改文件系统更改序列化策略并保持与本地的连接,但是我基本上是在重新实现 SSHFS。它完全扼杀了抽象。
FIFO(命名管道)与常规管道 (|) 有何不同?正如我从Wikipedia了解到的,与常规管道不同,FIFO 管道在进程结束后“继续存在”,并且可以在之后的某个时间删除。
但是如果进程基于包含管道 ( cat x | grep y
)的 shell 命令,如果我们将其存储在变量或文件中,我们可以“在进程之后保持活动状态”,那不就是一个 FIFO 吗?
此外,常规管道也具有它获得的第一个标准输出,作为另一个命令的标准输入,所以它不也是一种先进先出管道吗?
fifo ×10
pipe ×5
cat ×2
shell-script ×2
tail ×2
files ×1
filesystems ×1
inotify ×1
ipc ×1
linux-kernel ×1
monitoring ×1
pv ×1
socket ×1
sshfs ×1