2

名前付きパイプと通信する2つのプロセスを並行して実行しました。奇妙な動作に気付きました: すべての書き込みの後に読み取りが続くか、またはその逆でなければなりません! ルールを破ると、プログラムがハングし、ctrl+C で終了すると、子プロセスはハングし、再読み込みができなくなります。

私の例:

#!/bin/bash
shopt -u failglob
shopt -s extglob nullglob dotglob

function london (){
   local message answer fifo id return exitcode
   fifo=fifo_$RANDOM.$RANDOM.$RANDOM.$$
   mkfifo ${fifo}
   #trap 'rm -rf "$fifo"' EXIT
   ( berlin $fifo ) &
   id=$!
   echo "parent id: $$, child id: $id"
   message='Greetings from London!(1)'
   echo "$message" > $fifo
   echo "1. parent sent it's 1st message"
   #*****write-to-write error!*****#
   message='Greetings from London!(2)'
   #read -r answer < $fifo
   echo "$message" > $fifo
   echo "2. parent sent it's 2nd message"
   wait
   rm -rf $fifo
}

function berlin (){
   local message answer fifo
   fifo=$1
   read -r answer < $fifo
   echo 'Berlin says:> '"$answer"
   #*****read-to-read error!*****#
   #echo 'next' > $fifo
   read -r answer < $fifo
   echo 'Berlin says:> '"$answer"
}

london

「write-to-write」または「read-to-read」メッセージを挿入したポイントの下に、問題を解決する2つのコメント行があり、上記のルールが不思議なことに成り立っていると思います!!! 何が起こっているのですか?

出力は次のとおりです。

parent id: 4921, child id: 4923
1. parent sent it's 1st message
2. parent sent it's 2nd message
Berlin says:> Greetings from London!(1)

ありがとう!

これですべてが明確になり、「読者の側からパイプを開いたままにしてください」という一言に凝縮されたと思います。

ここで、ループ内のコマンドの「一部」に 2 番目の入力ファイル記述子を追加したいとします。これどうやってするの?これが私の新しいベルリン関数です。

function berlin (){
   local message answer fifo
   fifo=$1
   while true; do
      read -r answer
      echo 'Berlin says:> '"$answer"
      #this fails!
      read -r -p "reading from fd0: " <&0
      if [[ $answer = 'quit' ]]; then
         break
      fi
   done < "$fifo" 3>"$fifo"
}

ご覧のとおり、パイプにはファイル記述子 3 を使用しますが、fd 0 から読み取ろうとすると、実際には fd 3 から読み取られます! これを達成する方法はありますか?

4

1 に答える 1

2

パイプが保持できるデータの量には制限があります。それらがいっぱいになるまで書き込みを行うと、データが読み出されるまで、以降の書き込みはすべてブロックされます。同様に、読み取るデータがパイプにない場合、読み取りはブロックされます。

最も重要なことは、物事を行う前に、パイプの両側に誰かがいる必要があるということです。したがって、2 番目のメッセージを書いた後、読者がパイプを見るという状況に遭遇します。したがって、これに関する限り、データはありません。その後、プライマリ プロセスが終了し、子プロセスはそのままになります。

これを修正するには、リーダー側を閉じないでください。while ループを使用して、その端を開いたままにします。そのようです:

#!/bin/bash
shopt -u failglob
shopt -s extglob nullglob dotglob

function london (){
   local message answer fifo id return exitcode
   fifo=fifo_$RANDOM.$RANDOM.$RANDOM.$$
   mkfifo ${fifo}
   #trap 'rm -rf "$fifo"' EXIT
   ( berlin $fifo ) & 
   id=$!
   echo "parent id: $$, child id: $id"
   message='Greetings from London!(1)'
   echo "$message" > $fifo
   echo "1. parent sent it's 1st message"
   #*****write-to-write error!*****#
   message='Greetings from London!(2)'
   #read -r answer < $fifo
   echo "$message" > $fifo
   echo "2. parent sent it's 2nd message"
   wait
   rm -rf $fifo
}

function berlin (){
   local message answer fifo
   fifo=$1
   while read -r answer
   do  
       echo 'Berlin says:> '"$answer"
   done < $fifo
}

london
于 2012-12-21T14:47:01.037 に答える