我做了2個並行運行的進程與命名管道進行通信。 我注意到一個奇怪的行爲:每一個寫都應該跟着一個閱讀,反之亦然! 如果我們違反了規則,程序就會掛起,如果我們用ctrl + C終止它,那麼孩子仍然掛起,這意味着它不能再重新讀取。2個進程之間使用的命名管道有什麼問題?
我的例子:
#!/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
在那裏我已經插入了「寫入到寫」或「讀閱讀」信息點有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)
謝謝!
我覺得現在一切都很清晰,並且在一個短語中被壓縮:「保持管道從閱讀器的部分打開」。
現在假設我想在循環內爲我的一些命令添加第二個輸入文件描述符;我怎樣才能做到這一點? 這裏是我的新柏林功能:
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閱讀!有沒有辦法做到這一點?
是啊,這是正確的答案,通過完整的機會,我發現這個(http://stackoverflow.com/questions/4290684/using-named-pipes-with-bash-problem-with-data -loss?rq = 1),實際上支持你的答案!謝謝!當然,一根管子的「數據量」是多少? 2^20個字節還是什麼? – centurian
...和最後一個問題:是否可以接受而不是使用成對讀寫的循環?關於代碼效率(我懷疑我們一次又一次地重新打開管道,這是不好的!) – centurian
@centurian命名管道一直存在,直到你刪除它,所以使用while循環非常有效。要檢查管道的大小,請在bash中使用'ulimit -a'來獲取當前設置的管道大小。但是,正如我所提到的,如果管道已滿,作者將會阻止,並且當有額外的空間時,它將繼續寫入而不會丟失數據。 –