【问题标题】:Example of using named pipes in Linux shell (Bash)在 Linux shell (Bash) 中使用命名管道的示例
【发布时间】:2011-05-06 01:35:36
【问题描述】:

有人可以发布一个在 Linux 上的 Bash 中使用命名管道的简单示例吗?

【问题讨论】:

    标签: linux bash shell pipe named-pipes


    【解决方案1】:

    命令如下:

    mkfifo named_pipe
    echo "Hi" > named_pipe &
    cat named_pipe
    

    第一个命令创建管道。

    第二个命令写入管道(阻塞)。 & 将其置于后台,因此您可以继续在同一个 shell 中键入命令。当 FIFO 被下一条命令清空时,它将退出。

    最后一个命令从管道中读取。

    【讨论】:

    • 我会将 # 更改为 $,因此它不会全部被注释(并且不以 root 身份运行!)
    • 习惯上,“#”指的是根提示符(即,根shell 中的提示符)。这里没有任何东西需要在 root shell 中运行。
    • echo 将阻塞,因此如果在同一个 shell 中执行,它将不会运行,除非第二行以 & 结尾。
    【解决方案2】:

    命名管道实际使用的最佳示例之一...

    来自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
    

    【讨论】:

    • @hft mkfifo backpipe; nc -l 12345 0&lt;backpipe | nc www.google.com 80 1&gt;backpipe 怎么样?
    • 虽然这是一个有用的例子,但如果你正在构建这种性质的代理,你通常最好使用socat,这是一个基本上实现 非常 功能齐全的特定领域语言,用于构建代理和(在更有限的程度上)服务器。使用socat STDIO TCP:www.google.com:80 可以更可靠、更高效地完成这个特定示例。
    【解决方案3】:

    打开两个不同的外壳,并排放置。在两者中,转到/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 类型并查看此特定类型文件的详细信息。

    下一步是在脚本中编写代码!

    【讨论】:

    • 是否可以对fifo进行非阻塞写入?
    【解决方案4】:

    1号航站楼:

    $ mknod new_named_pipe p
    $ echo 123 > new_named_pipe
    
    • 终端 1 创建了一个命名管道。
    • 它使用 echo 在其中写入数据。
    • 由于没有接收端而被阻塞(因为命名和未命名的管道都需要接收和写入端)

    2号航站楼:

    $ cat new_named_pipe
    $ 123
    $ 
    
    • 从终端 2 添加数据的接收端。
    • 它使用 cat 读取其中的数据。
    • 由于new_named_pipe 的接收端和写入端都在那里,它会显示信息和阻塞停止

    命名管道在 Linux 中无处不在,我们在ls -l 命令中看到的大多数字符和块文件都是字符和块管道(所有这些都驻留在 /dev 中)。 这些管道可以是阻塞的和非阻塞的,主要优点是它们为 IPC 提供了最简单的方法。

    【讨论】:

      【解决方案5】:

      创建命名管道

      $ 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
      

      【讨论】:

      • 没有complete(-ish)的例子,所以我写了一个。
      猜你喜欢
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      • 1970-01-01
      • 2016-04-01
      • 1970-01-01
      • 2014-12-21
      • 2023-04-06
      • 1970-01-01
      相关资源
      最近更新 更多