我正在编写一个脚本来设置机器环境。我能够在计算机上放置启动脚本,因此我试图在我的“工作站”计算机上的Unix中使用命名管道mkfifo
,当这些新计算机联机时,它们将侦听来自这些新计算机的写入。 / p>
问题是,我无法控制这些计算机何时可以联机。总共有超过20台机器正在同时启动,我试图模拟命名管道被多次写入的效果,然后它才有机会读取并产生令人吃惊的结果。...
我写了两个小的测试脚本:
mkfifogen.sh
#!/bin/bash
mkfifo h
testing=""
sleep 10
for((i=0;i<5;i++));do
echo $I
while read line;do
testing+="$line"
done < h
done
echo "$testing"
rm -f h
和
mkfifowrite.sh
#!/bin/bash
for((i=0;i<5;i++));do
echo "this is a test $i" > h
done
当我先运行mkfifogen.sh之后再运行mkfifowrite.sh时,输出如下所示
0
1
2
然后,mkfifowrite.sh脚本退出并且mkfifogen.sh脚本挂起
然后我必须再运行mkfifowrite.sh脚本3次,并且每次它都会导致mkfifogen.sh脚本的输出再增加一次。上一次运行将导致测试值输出4次,因此在运行4次mkfifowrite.sh脚本和运行一次mkfifogen.sh脚本后,我的输出如下所示:
0
1
2
3
4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
运行mkfifogen.sh和mkfifowrite.sh一次后,我希望看到的内容是这样的:
0
1
2
3
4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
我已经在网上四处逛逛了,对此有一些神秘的答案,但是我似乎对它们没有多大意义。我觉得此链接可能会保留我的答案,但是我不确定https://unix.stackexchange.com/questions/68146/what-are-guarantees-for-concurrent-writes-into-a-named-pipe
TL; DR:
如何确保所有对命名管道的写入,无论它们连续执行的快慢如何,均由读取独立处理?
答案 0 :(得分:0)
阅读器读取直到EOF,然后重复直到收到5个EOF。
编写器打开和关闭管道5次。编写器每次关闭管道时,都会存在潜在的EOF条件。直到读者尝试读取它(在读取之前编写的所有内容之后),它才成为真正的EOF。
在潜在的EOF阶段,有一场比赛。编写器正在递增i
并准备打开管道以再次写入,而阅读器正在完成read
命令并处理结果,然后它将尝试再次读取。
如果在阅读器尝试进行读取之前,写入器执行了打开操作,则潜在的EOF条件消失。如果在写入器不再连接到管道时读取器尝试读取,则会发生EOF。
如您所见,当一个管道有多个写入器时(无论是顺序写入器还是并行写入器),EOF会很麻烦。您不能期望它们能够可靠地出现在来自不同作者的消息之间。我的解决方法是设计协议,以使阅读器不需要EOF来识别消息的结尾,然后让阅读器以读+写模式打开管道,这样总是至少是一名现有作家,并且EOF将永远不会发生。
将邮件保持在PIPE_BUF
大小以免被拆分是一个单独的问题,您也必须注意。