mkfifo 管道、文件描述符和 ImageMagick(转换)

mkfifo 管道、文件描述符和 ImageMagick(转换)

我在使用命名管道(即使用 创建)和文件描述符来重定向输出并在 ImageMagick ( )mkfifo中抓取输入时遇到了麻烦。convert

基本上,使用以下bash代码(嗯,与我正在尝试的更简单的等效代码)脚本会挂起并且不会显示图像:

#!/bin/bash
mkfifo myPipe                              # Create a named pipe
exec 3<>myPipe                             # I/O file descriptor using the pipe
convert rose: -resize 640x480\! png:fd:3   # Write the image to the pipe
convert png:fd:3 win:                      # To read from the pipe using the file descriptor
exec 3>&-                                  # Close the file descriptor
rm myPipe                                  # Close and remove the pipe

做了一些研究,我看到这里这一段(来自乔纳森·莱弗勒的回答):

当打开 FIFO 进行读取时,它会阻塞调用进程(通常)。当进程打开 FIFO 进行写入时,读取器将被解除阻塞。当写入器关闭 FIFO 时,读取过程会得到 EOF(要读取 0 个字节),除了关闭 FIFO 并重新打开之外,没有其他任何操作。

为了避免这种情况,我尝试使用 Mark Edgar 的解决方案,其中包含以下说明(代码取自答案):

# Create pipe and start reader.
mkfifo pipe
cat pipe &
# Open pipe for writing.
exec 3>pipe
echo one >&3
echo two >&3
# Close pipe.
exec 3>&-

不幸的是,我需要从管道中读取并使用文件描述符写入它(即fd:X使用convert)。我怎样才能在没有悬挂问题的情况下实现这一目标?

答案1

问题是,虽然

exec 3<>myPipe

同时打开 FIFO 的 R 端和 W 端,从而防止出现死锁,

convert rose: -resize 640x480\! png:fd:3

是一个普通/前台命令,需要在下一个命令运行之前完成。因为它正在向 FIFO 写入可能大量的数据,所以它不会完成,而是在 FIFO 缓冲区已满时被阻塞,从而有效地使脚本陷入死锁。

为了防止这种情况发生,您需要将此命令放在后台,以便下一个进程可以同时耗尽 FIFO,防止它被填满。

正如我在评论中提到的,在这种情况下,我建议使用常规管道而不是命名管道:

convert rose: -resize 640x480\! png:fd:1 | 
   convert png:fd:0 win:

如果您担心代码行变得太长,您可以通过以以下方式结束行\或在需要右侧的标记后添加换行符(例如||&&|像我所做的那样)来创建延续行(我也倾向于缩进我的连续行以获得更好的可读性,但这纯粹是可选的)。

相关内容