Bashで双方向パイプを作成するには?

Bashで双方向パイプを作成するには?

ファイル記述子を読み書きするプログラムがあります3。私はそれがfdに書き、3パイプの反対側に対話的に書き込むことができるようにしたいと思います。プログラムは同じfdを読む必要があります。mkfifo()を使用してパイプを作成し、mkfifo /tmp/my_pipeパイプの一端をfd 3./prog &3>/tmp/my_pipe)に再マップすることができます。私はKeep Pipe Openを使用していますcat /tmp/my_pipe。しかし、プロセスがfdを読み取ろう3としたらSIGTTIN

ベストアンサー1

(少なくとも)Linuxベースのシステムでは、FIFOまたは名前付きパイプは一方向です。あなたの場合、同じFIFOを読み書きするプログラムが欲しいです。パイプの内部バッファを超えるとデッドロックに陥る可能性があるため、これはさらに難しくなります。

2つの一般的な事項。

  1. 2人のリーダーを持つことはできません。これにより、読み取りが非決定的にインターリーブされ、データが2つのリーダー間で共有されます。同じデータを両方のリーダーにコピーしません。

  2. 複数のビルダーを持つことができますが、出力データはパイプから受け取った順序で再インターリーブされます。作成者が慎重に同期しないと、などFirst writerのデータが横説説Second writerと見なされる可能性がありますFirSecond wrstwrititerer

この回答の下部にあるプログラムを使用して、異なるターミナルセッションで次の2つのシナリオを実行することを検討してください。それからあなた自身の変形を試してみてください。

First terminal                Second terminal               Third terminal
--------------------          --------------------          --------------------
./fifo.sh read                ./fifo.sh read                ./fifo.sh write /etc/hosts

First terminal                Second terminal               Third terminal
--------------------          --------------------          --------------------
./fifo.sh write /etc/passwd   ps -ef | ./fifo.sh write      ./fifo.sh read

First terminal                Second terminal               Third terminal
--------------------          --------------------          --------------------
./fifo.sh both /etc/passwd

スクリプトfifo.shは次のとおりです。

#!/bin/bash
#
pipe=/tmp/mypipe


########################################################################
# Reader
#
doRead()
{
    echo "Reading from pipe $pipe" >&2
    nl <"$pipe"
}


########################################################################
# Writer. We pause after every line (for effect)
#
doWrite()
{
    [[ $# -eq 0 ]] && set -- -
    echo "Writing to pipe $pipe" >&2
    cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >>"$pipe"
}


########################################################################
# Reader-Writer. We pause after every line (for effect)
#
doBoth()
{
    [[ $# -eq 0 ]] && set -- -
    echo "Reading and writing to pipe $pipe" >&2
    exec 3<>"$pipe"
    nl <&3 & readPID=$!
    cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >&3
    kill $readPID 2>/dev/null
}


########################################################################
#
action="$1"
shift

if [[ ! -p "$pipe" ]]
then
    echo "Creating pipe $pipe" >&2
    mkfifo "$pipe"
fi


case "$action" in
    read*)      doRead "$@" ;;
    write*)     doWrite "$@" ;;
    both)       doBoth "$@" ;;
esac

おすすめ記事