我想打开一个程序来写入命名管道,但是直到有人真正从命名管道中读取它才会写入。这是可以实现的吗?我怎么知道何时读取管道?
3 回答
写入管道实际上会阻塞,直到有人从管道读取
$ mkfifo f
$ printf "%s\n" "a" "b" "c" "d" > f & # on bg otherwise it blocks until someone reads it
$ cat < f
a
b
c
d
[1]+ Done printf "%s\n" "a" "b" "c" "d" > f
printf
所以你知道在上面的例子中何时读取管道是Done。
因此,一旦有人从管道中读取,等待运行命令可以实现为
printf "%s\n" > f && run_some_command
但是如果命令只是向管道发送数据(在这里推测),您可以直接发送数据,因为它们只会在有人从管道读取时发送
some_command > f # will block until f is read from
另一种查找是否以及谁在读取或写入管道的方法是lsof
. 尝试
$ lsof f
并且所有f
读取或写入的进程都将与其 pid、进程名称、读取或写入操作一起列出。请参阅手册页。
除了实现锁定文件或其他信号量/标志之外,我认为没有办法判断命名管道是否具有侦听器。但是,您也许能够检测到另一个方向的事物。 Linus Akesson 写了一篇关于使用管道模拟逻辑门的博客文章。(这是一本引人入胜的超级极客读物。)为了实现他的想法,他需要编写一个工具来检查管道是否有数据等待,而无需实际将数据从管道中取出。
您可以获取他的代码,为您的平台编译它,然后拥有一个工具,该工具仅在确认数据正在等待通过它发送时才从管道中读取。在不知道您真正想要实现的目标的情况下,我不知道此解决方案是否适用于您的实际问题。
底线是命名管道没有缓冲,并且在不使用可能特定于平台的黑客的情况下不提供状态指示。要么发送进程等待接收者,要么接收进程等待发送者。
您可能希望使用比命名管道更高级的消息传递系统。
命名管道在文件系统中是可见的,并且可以像其他文件一样读写:
$ ls -la /tmp/testpipe
prw-r--r-- 1 mitch users 0 2009-03-25 12:06 /tmp/testpipe|
命名管道是通过 mkfifo 或 mknod 创建的:
$ mkfifo /tmp/testpipe
$ mknod /tmp/testpipe p
以下 shell 脚本从管道中读取。如果管道不存在,它首先创建管道,然后循环读取,直到看到“退出”:
#!/bin/bash
pipe=/tmp/testpipe
trap "rm -f $pipe" EXIT
if [[ ! -p $pipe ]]; then
mkfifo $pipe
fi
while true
do
if read line <$pipe; then
if [[ "$line" == 'quit' ]]; then
break
fi
echo $line
fi
done
echo "Reader exiting"