【发布时间】:2011-05-06 01:35:36
【问题描述】:
有人可以发布一个在 Linux 上的 Bash 中使用命名管道的简单示例吗?
【问题讨论】:
标签: linux bash shell pipe named-pipes
有人可以发布一个在 Linux 上的 Bash 中使用命名管道的简单示例吗?
【问题讨论】:
标签: linux bash shell pipe named-pipes
命令如下:
mkfifo named_pipe
echo "Hi" > named_pipe &
cat named_pipe
第一个命令创建管道。
第二个命令写入管道(阻塞)。 & 将其置于后台,因此您可以继续在同一个 shell 中键入命令。当 FIFO 被下一条命令清空时,它将退出。
最后一个命令从管道中读取。
【讨论】:
echo 将阻塞,因此如果在同一个 shell 中执行,它将不会运行,除非第二行以 & 结尾。
命名管道实际使用的最佳示例之一...
来自http://en.wikipedia.org/wiki/Netcat:
另一个有用的行为是使用
netcat作为代理。端口和主机都可以重定向。看这个例子:nc -l 12345 | nc www.google.com 80端口 12345 代表请求。
这会在端口 12345 上启动
nc服务器,并且所有连接都会重定向到google.com:80。如果网络浏览器向nc发出请求,请求将被发送到谷歌,但响应不会被发送到网络浏览器。那是因为管道是单向的。这可以使用命名管道来重定向输入和输出。mkfifo backpipe nc -l 12345 0<backpipe | nc www.google.com 80 1>backpipe
【讨论】:
mkfifo backpipe; nc -l 12345 0<backpipe | nc www.google.com 80 1>backpipe 怎么样?
socat STDIO TCP:www.google.com:80 可以更可靠、更高效地完成这个特定示例。
打开两个不同的外壳,并排放置。在两者中,转到/tmp/ 目录:
cd /tmp/
在第一种类型中:
mkfifo myPipe
echo "IPC_example_between_two_shells">myPipe
在第二个中,输入:
while read line; do echo "What has been passed through the pipe is ${line}"; done<myPipe
在您在第二个 shell 中执行代码的第二部分之前,第一个 shell 不会给您任何提示。这是因为fifo读写阻塞。
您还可以通过ls -al myPipe 查看 FIFO 类型并查看此特定类型文件的详细信息。
下一步是在脚本中编写代码!
【讨论】:
1号航站楼:
$ mknod new_named_pipe p
$ echo 123 > new_named_pipe
2号航站楼:
$ cat new_named_pipe
$ 123
$
new_named_pipe 的接收端和写入端都在那里,它会显示信息和阻塞停止命名管道在 Linux 中无处不在,我们在ls -l 命令中看到的大多数字符和块文件都是字符和块管道(所有这些都驻留在 /dev 中)。
这些管道可以是阻塞的和非阻塞的,主要优点是它们为 IPC 提供了最简单的方法。
【讨论】:
$ mkfifo pipe_name
在类 Unix 中,命名管道 (FIFO) 是一种特殊类型的文件,没有内容。 mkfifo 命令在文件系统上创建管道(为其分配名称),但不打开它。您需要像任何其他文件一样单独打开和关闭它。
当您需要从/到多个进程进行管道传输或无法使用匿名管道连接两个进程时,命名管道非常有用。它们可以以多种方式使用:
与另一个进程并行:
$ echo 'Hello pipe!' > pipe_name & # runs writer in a background
$ cat pipe_name
Hello pipe!
这里 writer 沿着 reader 运行,允许进程之间的实时通信。
Sequentially with file descriptors:
$ # open the pipe on auxiliary FD #5 in both ways (otherwise it will block),
$ # then open descriptors for writing and reading and close the auxiliary FD
$ exec 5<>pipe_name 3>pipe_name 4<pipe_name 5>&-
$
$ echo 'Hello pipe!' >&3 # write into the pipe through FD #3
...
$ exec 3>&- # close the FD when you're done
$ # (otherwise reading will block)
$ cat <&4
Hello pipe!
...
$ exec 4<&-
实际上,通过管道进行通信可以是顺序的,但它是limited to a buffer size of 64 KB。
最好使用描述符来传输多条数据,以减少开销。
有条件的with signals:
$ handler() {
> cat <&3
>
> exec 3<&-
> trap - USR1 # unregister signal handler (see below)
> unset -f handler writer # undefine the functions
> }
$
$ exec 4<>pipe_name 3<pipe_name 4>&-
$ trap handler USR1 # register handler for signal USR1
$
$ writer() {
> if <condition>; then
> kill -USR1 $PPID # send the signal USR1 to a specified process
> echo 'Hello pipe!' > pipe_name
> fi
> }
$ export -f writer # pass the function to child shells
$
$ bash -c writer & # can actually be run sequentially as well
$
Hello pipe!
FD 允许在 shell 准备好接收数据之前开始数据传输。顺序使用时需要。
如果管道缓冲区已满,应在数据之前发送信号以防止死锁。
当所有描述符都关闭时,管道本身(及其内容)将被销毁。剩下的只是一个名字。
要使管道匿名且在给定名称下不可用(可以在管道仍然打开时完成),您可以使用rm 控制台命令(这与mkfifo 命令相反):
$ rm pipe_name
【讨论】: